4497: Create LowerCtx on the fly r=matklad a=edwin0cheng

Previously we create `LowerCtx` at the beginning of lowering, however, the hygiene content is in fact changing between macro expression expanding. 

This PR change it to create the `LowerCtx` on the fly to fix above bug.

However, #4465 is not fixed by this PR, the goto-def is still not work yet. It only fixed the infer part. 

Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2020-05-18 11:03:44 +00:00 committed by GitHub
commit 9bdedbbcaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 9 deletions

View File

@ -60,13 +60,10 @@ pub(super) fn lower(
params: Option<ast::ParamList>,
body: Option<ast::Expr>,
) -> (Body, BodySourceMap) {
let ctx = LowerCtx::new(db, expander.current_file_id.clone());
ExprCollector {
db,
def,
expander,
ctx,
source_map: BodySourceMap::default(),
body: Body {
exprs: Arena::default(),
@ -83,7 +80,6 @@ struct ExprCollector<'a> {
db: &'a dyn DefDatabase,
def: DefWithBodyId,
expander: Expander,
ctx: LowerCtx,
body: Body,
source_map: BodySourceMap,
}
@ -122,6 +118,10 @@ fn collect(
(self.body, self.source_map)
}
fn ctx(&self) -> LowerCtx {
LowerCtx::new(self.db, self.expander.current_file_id)
}
fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
let src = self.expander.to_source(ptr);
let id = self.make_expr(expr, Ok(src.clone()));
@ -268,7 +268,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
};
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
let generic_args =
e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it));
e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
self.alloc_expr(
Expr::MethodCall { receiver, method_name, args, generic_args },
syntax_ptr,
@ -373,7 +373,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
}
ast::Expr::CastExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref());
let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
}
ast::Expr::RefExpr(e) => {
@ -396,7 +396,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
for param in pl.params() {
let pat = self.collect_pat_opt(param.pat());
let type_ref =
param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
args.push(pat);
arg_types.push(type_ref);
}
@ -404,7 +404,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
let ret_type = e
.ret_type()
.and_then(|r| r.type_ref())
.map(|it| TypeRef::from_ast(&self.ctx, it));
.map(|it| TypeRef::from_ast(&self.ctx(), it));
let body = self.collect_expr_opt(e.body());
self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
}
@ -507,7 +507,8 @@ fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
.map(|s| match s {
ast::Stmt::LetStmt(stmt) => {
let pat = self.collect_pat_opt(stmt.pat());
let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
let type_ref =
stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
Statement::Let { pat, type_ref, initializer }
}

View File

@ -563,6 +563,37 @@ fn main() {
);
}
#[test]
fn issue_4465_dollar_crate_at_type() {
assert_snapshot!(
infer(r#"
pub struct Foo {}
pub fn anything<T>() -> T {
loop {}
}
macro_rules! foo {
() => {{
let r: $crate::Foo = anything();
r
}};
}
fn main() {
let _a = foo!();
}
"#), @r###"
45..60 '{ loop {} }': T
51..58 'loop {}': !
56..58 '{}': ()
!0..31 '{letr:...g();r}': Foo
!4..5 'r': Foo
!18..26 'anything': fn anything<Foo>() -> Foo
!18..28 'anything()': Foo
!29..30 'r': Foo
164..188 '{ ...!(); }': ()
174..176 '_a': Foo
"###);
}
#[test]
fn issue_4053_diesel_where_clauses() {
assert_snapshot!(