private TypeHolder _eraseTypeVariables(Map<String, TypeHolder> variable2Holder, Set<String> visitedVariables, TypeHolder typeHolder) {
		
		if (typeHolder.getRawClass() == null) {
			if (variable2Holder.containsKey(typeHolder.getName())) {
				TypeHolder th = variable2Holder.get(typeHolder.getName());
				WildcardBound newWildcardBound = typeHolder.getWildcardBound() == WildcardBound.NO_WILDCARD ? th.getWildcardBound() : typeHolder.getWildcardBound();
				visitedVariables.add(typeHolder.getName());
				return th.changeWildcardBound(newWildcardBound);
			}
			else {
				if (visitedVariables.contains(typeHolder.getName())) {
					return TypeHolder.newInstance(Object.class).changeWildcardBound(WildcardBound.UPPER);
				}
				else {
					visitedVariables.add(typeHolder.getName());
					for (TypeVariableHolder typeVariable : this.typeVariables) {
						if (typeVariable.getName().equals(typeHolder.getName())) {
							if (typeVariable.getTypeParams().size() > 0) {
								TypeHolder th = _eraseTypeVariables(variable2Holder, visitedVariables, typeVariable.getTypeParams().get(0)).changeWildcardBound(WildcardBound.UPPER);
								variable2Holder.put(typeHolder.getName(), th);
								return th;
							}
							else {
								TypeHolder th = TypeHolder.newInstance(Object.class).changeWildcardBound(WildcardBound.UPPER);
								variable2Holder.put(typeHolder.getName(), th);
								return th;
							}
						}
					}
					
					throw new IllegalStateException();
				}
			}
		}
		else {
			
			List<TypeHolder> newTypeParams = new ArrayList<TypeHolder>();
			for (TypeHolder typeParam : typeHolder.getTypeParams()) {
				TypeHolder newTypeParam = _eraseTypeVariables(variable2Holder, visitedVariables, typeParam);
				if (typeParam.getWildcardBound() != WildcardBound.NO_WILDCARD) {
					newTypeParam = newTypeParam.changeWildcardBound(typeParam.getWildcardBound());
				}
				newTypeParams.add(newTypeParam);
			}
			
			return TypeHolder.newInstance(typeHolder.getRawClass(), newTypeParams );
		}
	}