-
Notifications
You must be signed in to change notification settings - Fork 183
Add scalars to TypeName
#394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add scalars to TypeName
#394
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good start! I think we can remove the code around scalar values. What I think we will need though is
(1) to modify the parser so that it permits parsing tuples like (T1, ..., Tn)
as types
(2) then either to modify the parser so that it recognizes bool
, u8
, etc as keywords or to modify the lowering code that maps type names to types so that it has hard-coded knowledge of bool
and friends.
Modifying parser to accept tuples:
Just add "(" ... ")"
into this entry, and extend Ty
to include Ty::Tuple
:
chalk/chalk-parse/src/parser.lalrpop
Lines 180 to 192 in 154020e
TyWithoutFor: Ty = { | |
<n:Id> => Ty::Id { name: n}, | |
"fn" "(" <t:Ty> ")" => Ty::ForAll { | |
lifetime_names: vec![], | |
ty: Box::new(t) | |
}, | |
"dyn" <b:Plus<QuantifiedInlineBound>> => Ty::Dyn { | |
bounds: b, | |
}, | |
<n:Id> "<" <a:Comma<Parameter>> ">" => Ty::Apply { name: n, args: a }, | |
<a:AliasTy> => Ty::Alias { alias: a }, | |
"(" <Ty> ")", | |
}; |
You'll have to modify the match here in lowering to include tuple too:
chalk/chalk-integration/src/lowering.rs
Line 977 in 154020e
match *self { |
Modifying parser to know bools etc:
You could do the same for bools, integers, etc as you did for tuples, or you could modify lowering, as described next. I don't have a strong opinion about which is better -- this is just the chalk testing harness, after all -- I think I'd go for modifying the parser, it seems mildly easier to me.
Modifying lowering to hard-code bools etc:
Here is the lowering code that actually looks up a name:
chalk/chalk-integration/src/lowering.rs
Lines 79 to 96 in 154020e
fn lookup_type(&self, name: Identifier) -> LowerResult<TypeLookup> { | |
if let Some(k) = self | |
.parameter_map | |
.get(&chalk_ir::ParameterKind::Ty(name.str)) | |
{ | |
return Ok(TypeLookup::Parameter(*k)); | |
} | |
if let Some(id) = self.struct_ids.get(&name.str) { | |
return Ok(TypeLookup::Struct(*id)); | |
} | |
if let Some(_) = self.trait_ids.get(&name.str) { | |
return Err(RustIrError::NotStruct(name)); | |
} | |
Err(RustIrError::InvalidTypeName(name)) | |
} |
Right now it's hard-coded to type parameters or the names of structs. It could have some code at the end that's like "if this is the string bool, then return TypeLookup::Bool
" etc. You would also have to modify this code that converts a type like foo
into the chalk-ir type to understand those results:
chalk/chalk-integration/src/lowering.rs
Lines 978 to 996 in 154020e
Ty::Id { name } => match env.lookup_type(name)? { | |
TypeLookup::Struct(id) => { | |
let k = env.struct_kind(id); | |
if k.binders.len() > 0 { | |
Err(RustIrError::IncorrectNumberOfTypeParameters { | |
identifier: name, | |
expected: k.binders.len(), | |
actual: 0, | |
}) | |
} else { | |
Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy { | |
name: chalk_ir::TypeName::Struct(id), | |
substitution: chalk_ir::Substitution::empty(interner), | |
}) | |
.intern(interner)) | |
} | |
} | |
TypeLookup::Parameter(d) => Ok(chalk_ir::TyData::BoundVar(d).intern(interner)), | |
}, |
e27651e
to
e966087
Compare
Thank you for the very helpful review! Here's the status of the PR:
So from my perspective there's 3 things left to do:
I'll try to get those done tomorrow if I'm able to! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking real close! Left one suggestion around how to handle tuples (and a suggestion for cleaning up the parser)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! A few comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! I think this is just about ready to land, modulo a rebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was said on Zulip, but I think what you want to do is to modify the code that runs in this match arm
chalk/chalk-solve/src/clauses.rs
Lines 296 to 298 in f438d7e
DomainGoal::WellFormed(WellFormed::Ty(ty)) | |
| DomainGoal::IsUpstream(ty) | |
| DomainGoal::DownstreamType(ty) => match_ty(builder, environment, ty)?, |
So presumably that function match_ty
:
chalk/chalk-solve/src/clauses.rs
Lines 392 to 407 in f438d7e
/// Examine `T` and push clauses that may be relevant to proving the | |
/// following sorts of goals (and maybe others): | |
/// | |
/// * `DomainGoal::WellFormed(T)` | |
/// * `DomainGoal::IsUpstream(T)` | |
/// * `DomainGoal::DownstreamType(T)` | |
/// * `DomainGoal::IsFullyVisible(T)` | |
/// * `DomainGoal::IsLocal(T)` | |
/// | |
/// Note that the type `T` must not be an unbound inference variable; | |
/// earlier parts of the logic should "flounder" in that case. | |
fn match_ty<I: Interner>( | |
builder: &mut ClauseBuilder<'_, I>, | |
environment: &Environment<I>, | |
ty: &Ty<I>, | |
) -> Result<(), Floundered> { |
It should, if ty
is a built-in scalar type, just generate a clause that declare them to be well-formed. You can basically just add them to this existing arm that handles generic placeholders, which are also always assumed to be well-formed:
chalk/chalk-solve/src/clauses.rs
Lines 411 to 413 in f438d7e
TyData::Placeholder(_) => { | |
builder.push_clause(WellFormed::Ty(ty.clone()), Some(FromEnv::Ty(ty.clone()))); | |
} |
ade9164
to
4e62e3d
Compare
4e62e3d
to
30cd25e
Compare
30cd25e
to
1ca8168
Compare
1ca8168
to
2fd7fb7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Just one nit and then let's land this.
chalk-solve/src/clauses.rs
Outdated
name: TypeName::Scalar(_), | ||
.. | ||
}) => { | ||
builder.push_fact(WellFormed::Ty(ty.clone())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this logic should move into match_type_name
chalk-solve/src/clauses.rs
Outdated
@@ -454,6 +460,8 @@ fn match_type_name<I: Interner>(builder: &mut ClauseBuilder<'_, I>, name: TypeNa | |||
.db | |||
.associated_ty_data(type_id) | |||
.to_program_clauses(builder), | |||
TypeName::Scalar(_) => (), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i.e., right here
@@ -454,6 +460,8 @@ fn match_type_name<I: Interner>(builder: &mut ClauseBuilder<'_, I>, name: TypeNa | |||
.db | |||
.associated_ty_data(type_id) | |||
.to_program_clauses(builder), | |||
TypeName::Scalar(_) => (), | |||
TypeName::Tuple(_) => (), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is right, though it may change as we tweak our def'n of implied bounds
Thanks! I moved the logic but had to change the type signature of A somewhat reasonable alternative is to pass |
It seems fine as is to me, thanks! |
Part of #368 ; spun off of #371