Skip to content

Commit fedf314

Browse files
asukaminato0721meta-codesync[bot]
authored andcommitted
fix panic: entered unreachable code: Expected a QuantifiedValue, got @_ #1659 (#1884)
Summary: Fixes #1659 scoped_type_params no longer asks the solver to resolve each TypeParameter (which caused the recursive Type::Var). It now reads the TypeParameter binding directly, builds the Quantified via the shared helper quantified_from_type_parameter, and takes the active ErrorCollector so diagnostics still flow to the correct sink. Call sites in class tparams, function tparams, and scoped type aliases were updated to pass errors. Pull Request resolved: #1884 Test Plan: Added a regression test that models class C[T: C] to lock in the crash reported in #1659. Reviewed By: stroxler Differential Revision: D89520905 Pulled By: rchen152 fbshipit-source-id: 7b70551fc29214e4c9cfd26d71cd1d150a71f989
1 parent f0b8d7b commit fedf314

4 files changed

Lines changed: 82 additions & 67 deletions

File tree

pyrefly/lib/alt/class/tparams.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
4040
scoped_type_params: Option<&TypeParams>,
4141
errors: &ErrorCollector,
4242
) -> Arc<TParams> {
43-
let scoped_tparams = self.scoped_type_params(scoped_type_params);
43+
let scoped_tparams = self.scoped_type_params(scoped_type_params, errors);
4444
self.validated_tparams(name.range, scoped_tparams, TParamsSource::Class, errors)
4545
}
4646

@@ -52,7 +52,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
5252
legacy: &[Idx<KeyLegacyTypeParam>],
5353
errors: &ErrorCollector,
5454
) -> Arc<TParams> {
55-
let scoped_tparams = self.scoped_type_params(scoped_type_params);
55+
let scoped_tparams = self.scoped_type_params(scoped_type_params, errors);
5656
let legacy_tparams = legacy
5757
.iter()
5858
.filter_map(|key| self.get_idx(*key).deref().parameter().cloned())

pyrefly/lib/alt/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
459459
&mut parent_param_hints,
460460
errors,
461461
);
462-
let mut tparams = self.scoped_type_params(def.type_params.as_deref());
462+
let mut tparams = self.scoped_type_params(def.type_params.as_deref(), errors);
463463
let legacy_tparams = legacy_tparams
464464
.iter()
465465
.filter_map(|key| self.get_idx(*key).deref().parameter().cloned());

pyrefly/lib/alt/solve.rs

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,23 +1374,79 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
13741374
})
13751375
}
13761376

1377-
pub fn scoped_type_params(&self, x: Option<&TypeParams>) -> Vec<TParam> {
1377+
fn quantified_from_type_parameter(
1378+
&self,
1379+
tp: &TypeParameter,
1380+
errors: &ErrorCollector,
1381+
) -> Quantified {
1382+
let restriction = if let Some(bound) = &tp.bound {
1383+
let bound_ty = self.expr_untype(bound, TypeFormContext::TypeVarConstraint, errors);
1384+
Restriction::Bound(bound_ty)
1385+
} else if let Some((constraints, range)) = &tp.constraints {
1386+
if constraints.len() < 2 {
1387+
self.error(
1388+
errors,
1389+
*range,
1390+
ErrorInfo::Kind(ErrorKind::InvalidTypeVar),
1391+
format!(
1392+
"Expected at least 2 constraints in TypeVar `{}`, got {}",
1393+
tp.name,
1394+
constraints.len(),
1395+
),
1396+
);
1397+
Restriction::Unrestricted
1398+
} else {
1399+
let constraint_tys = constraints.map(|constraint| {
1400+
self.expr_untype(constraint, TypeFormContext::TypeVarConstraint, errors)
1401+
});
1402+
Restriction::Constraints(constraint_tys)
1403+
}
1404+
} else {
1405+
Restriction::Unrestricted
1406+
};
1407+
let mut default_ty = None;
1408+
if let Some(default_expr) = &tp.default {
1409+
let default = self.expr_untype(
1410+
default_expr,
1411+
TypeFormContext::quantified_kind_default(tp.kind),
1412+
errors,
1413+
);
1414+
default_ty = Some(self.validate_type_var_default(
1415+
&tp.name,
1416+
tp.kind,
1417+
&default,
1418+
default_expr.range(),
1419+
&restriction,
1420+
errors,
1421+
));
1422+
}
1423+
Quantified::new(tp.unique, tp.name.clone(), tp.kind, default_ty, restriction)
1424+
}
1425+
1426+
pub fn scoped_type_params(
1427+
&self,
1428+
x: Option<&TypeParams>,
1429+
errors: &ErrorCollector,
1430+
) -> Vec<TParam> {
13781431
match x {
13791432
Some(x) => {
1380-
let get_quantified = |t: &Type| match t {
1381-
Type::QuantifiedValue(q) => (**q).clone(),
1382-
_ => unreachable!(
1383-
"{}:{:?}: Expected a QuantifiedValue, got {}",
1384-
self.module().path().as_path().display(),
1385-
x.range(),
1386-
t
1387-
),
1388-
};
13891433
let mut params = Vec::new();
13901434
for raw_param in x.type_params.iter() {
13911435
let name = raw_param.name();
1392-
let quantified =
1393-
get_quantified(self.get(&Key::Definition(ShortIdentifier::new(name))).ty());
1436+
let key = Key::Definition(ShortIdentifier::new(name));
1437+
let idx = self.bindings().key_to_idx(&key);
1438+
let binding = self.bindings().get(idx);
1439+
let quantified = match binding {
1440+
Binding::TypeParameter(tp) => {
1441+
self.quantified_from_type_parameter(tp, errors)
1442+
}
1443+
_ => unreachable!(
1444+
"{}:{:?}: Expected a TypeParameter binding, got {:?}",
1445+
self.module().path().as_path().display(),
1446+
x.range(),
1447+
binding
1448+
),
1449+
};
13941450
params.push(TParam {
13951451
quantified,
13961452
variance: PreInferenceVariance::PUndefined,
@@ -3430,57 +3486,8 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
34303486
},
34313487
Binding::Type(x) => x.clone(),
34323488
Binding::Global(global) => global.as_type(self.stdlib),
3433-
Binding::TypeParameter(box TypeParameter {
3434-
name,
3435-
unique,
3436-
kind,
3437-
bound,
3438-
default,
3439-
constraints,
3440-
}) => {
3441-
let restriction = if let Some(bound) = bound {
3442-
let bound_ty =
3443-
self.expr_untype(bound, TypeFormContext::TypeVarConstraint, errors);
3444-
Restriction::Bound(bound_ty)
3445-
} else if let Some((constraints, range)) = constraints {
3446-
if constraints.len() < 2 {
3447-
self.error(
3448-
errors,
3449-
*range,
3450-
ErrorInfo::Kind(ErrorKind::InvalidTypeVar),
3451-
format!(
3452-
"Expected at least 2 constraints in TypeVar `{}`, got {}",
3453-
name,
3454-
constraints.len(),
3455-
),
3456-
);
3457-
Restriction::Unrestricted
3458-
} else {
3459-
let constraint_tys = constraints.map(|constraint| {
3460-
self.expr_untype(constraint, TypeFormContext::TypeVarConstraint, errors)
3461-
});
3462-
Restriction::Constraints(constraint_tys)
3463-
}
3464-
} else {
3465-
Restriction::Unrestricted
3466-
};
3467-
let mut default_ty = None;
3468-
if let Some(default_expr) = default {
3469-
let default = self.expr_untype(
3470-
default_expr,
3471-
TypeFormContext::quantified_kind_default(*kind),
3472-
errors,
3473-
);
3474-
default_ty = Some(self.validate_type_var_default(
3475-
name,
3476-
*kind,
3477-
&default,
3478-
default_expr.range(),
3479-
&restriction,
3480-
errors,
3481-
));
3482-
}
3483-
Quantified::new(*unique, name.clone(), *kind, default_ty, restriction).to_value()
3489+
Binding::TypeParameter(tp) => {
3490+
self.quantified_from_type_parameter(tp, errors).to_value()
34843491
}
34853492
Binding::Module(m, path, prev) => {
34863493
let prev = prev
@@ -3516,7 +3523,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
35163523
let params_range = params.as_ref().map_or(expr.range(), |x| x.range);
35173524
Forallable::TypeAlias(*ta).forall(self.validated_tparams(
35183525
params_range,
3519-
self.scoped_type_params(params.as_ref()),
3526+
self.scoped_type_params(params.as_ref(), errors),
35203527
TParamsSource::TypeAlias,
35213528
errors,
35223529
))

pyrefly/lib/test/generic_basic.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ class C[T](Generic[T]): # E: Redundant
6868
"#,
6969
);
7070

71+
testcase!(
72+
test_class_type_params_can_reference_class,
73+
r#"
74+
class C[T: C](set[object]):
75+
pass
76+
"#,
77+
);
78+
7179
testcase!(
7280
test_type_argument_error_default,
7381
r#"

0 commit comments

Comments
 (0)