Skip to content

Commit 9701637

Browse files
fourlscirras
authored andcommitted
Specialize type constraints
We were previously not specializing type constraints, which was resulting in the constraint checking the unspecialized type parameter type for compatibility with the specialized type, which would always fail.
1 parent 932ab36 commit 9701637

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

delphi-frontend/src/main/java/au/com/integradev/delphi/type/generic/TypeSpecializationContextImpl.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package au.com.integradev.delphi.type.generic;
2020

21+
import au.com.integradev.delphi.type.generic.constraint.TypeConstraintImpl;
2122
import java.util.Comparator;
2223
import java.util.List;
2324
import java.util.Map;
@@ -28,6 +29,8 @@
2829
import org.sonar.plugins.communitydelphi.api.symbol.declaration.GenerifiableDeclaration;
2930
import org.sonar.plugins.communitydelphi.api.symbol.declaration.NameDeclaration;
3031
import org.sonar.plugins.communitydelphi.api.symbol.declaration.TypedDeclaration;
32+
import org.sonar.plugins.communitydelphi.api.type.Constraint;
33+
import org.sonar.plugins.communitydelphi.api.type.Constraint.TypeConstraint;
3134
import org.sonar.plugins.communitydelphi.api.type.Type;
3235
import org.sonar.plugins.communitydelphi.api.type.Type.TypeParameterType;
3336
import org.sonar.plugins.communitydelphi.api.type.TypeSpecializationContext;
@@ -66,14 +69,26 @@ public TypeSpecializationContextImpl(NameDeclaration declaration, List<Type> typ
6669
}
6770
}
6871

69-
private static boolean constraintViolated(Type parameter, Type argument) {
72+
private boolean constraintViolated(Type parameter, Type argument) {
7073
return parameter.isTypeParameter()
7174
&& ((TypeParameterType) parameter)
7275
.constraintItems().stream()
76+
.map(this::specializeConstraint)
7377
.map(constraint -> constraint.satisfiedBy(argument))
7478
.anyMatch(s -> !s);
7579
}
7680

81+
private Constraint specializeConstraint(Constraint constraint) {
82+
if (constraint instanceof TypeConstraint) {
83+
Type specializedType = getArgument(((TypeConstraint) constraint).type());
84+
if (specializedType != null) {
85+
return new TypeConstraintImpl(specializedType);
86+
}
87+
}
88+
89+
return constraint;
90+
}
91+
7792
@Override
7893
@Nullable
7994
public Type getArgument(Type parameter) {

delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiSymbolTableExecutorTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,8 @@ void testGenericImplicitSpecializations() {
11001100
@Test
11011101
void testGenericConstraints() {
11021102
execute("generics/Constraint.pas");
1103-
verifyUsages(11, 14, reference(20, 25), reference(53, 8));
1103+
verifyUsages(11, 14, reference(20, 25), reference(58, 8));
1104+
verifyUsages(31, 20, reference(68, 8));
11041105
}
11051106

11061107
@Test

delphi-frontend/src/test/resources/au/com/integradev/delphi/symbol/generics/Constraint.pas

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ TFoo<T: ICloneable, TTest, ISerializable> = class
2626
procedure Test;
2727
end;
2828

29+
TMock = class(TObject)
30+
public
31+
class function Mock<I: IInterface; T: I>(out Raw: T): I;
32+
end;
33+
2934
implementation
3035

3136
function TTest.SerializableClone: ISerializable;
@@ -60,4 +65,5 @@ procedure TFoo<T>.Test;
6065
initialization
6166
Foo := TFoo<TTest>.Create(Test);
6267
Foo.Test;
68+
TMock.Mock<ISerializable, TTest>(Test);
6369
end.

0 commit comments

Comments
 (0)