Skip to content

Commit 03d2d90

Browse files
committed
Auto merge of rust-lang#16811 - Veykril:snapshot, r=Veykril
fix: Fix method resolution snapshotting receiver_ty too early Accidental change in rust-lang/rust-analyzer#16749 presumably caused some type mismatches in webrender
2 parents 8f8bcfc + fdc527f commit 03d2d90

File tree

3 files changed

+48
-42
lines changed

3 files changed

+48
-42
lines changed

crates/hir-ty/src/infer/unify.rs

-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,6 @@ impl<'a> InferenceTable<'a> {
438438
where
439439
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
440440
{
441-
// TODO check this vec here
442441
self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback)
443442
}
444443

crates/hir-ty/src/method_resolution.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -1060,27 +1060,26 @@ fn iterate_method_candidates_by_receiver(
10601060
name: Option<&Name>,
10611061
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
10621062
) -> ControlFlow<()> {
1063+
let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
1064+
// We're looking for methods with *receiver* type receiver_ty. These could
1065+
// be found in any of the derefs of receiver_ty, so we have to go through
1066+
// that, including raw derefs.
1067+
table.run_in_snapshot(|table| {
1068+
let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
1069+
while let Some((self_ty, _)) = autoderef.next() {
1070+
iterate_inherent_methods(
1071+
&self_ty,
1072+
autoderef.table,
1073+
name,
1074+
Some(&receiver_ty),
1075+
Some(receiver_adjustments.clone()),
1076+
visible_from_module,
1077+
&mut callback,
1078+
)?
1079+
}
1080+
ControlFlow::Continue(())
1081+
})?;
10631082
table.run_in_snapshot(|table| {
1064-
let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
1065-
// We're looking for methods with *receiver* type receiver_ty. These could
1066-
// be found in any of the derefs of receiver_ty, so we have to go through
1067-
// that, including raw derefs.
1068-
table.run_in_snapshot(|table| {
1069-
let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
1070-
while let Some((self_ty, _)) = autoderef.next() {
1071-
iterate_inherent_methods(
1072-
&self_ty,
1073-
autoderef.table,
1074-
name,
1075-
Some(&receiver_ty),
1076-
Some(receiver_adjustments.clone()),
1077-
visible_from_module,
1078-
&mut callback,
1079-
)?
1080-
}
1081-
ControlFlow::Continue(())
1082-
})?;
1083-
10841083
let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
10851084
while let Some((self_ty, _)) = autoderef.next() {
10861085
iterate_trait_method_candidates(

crates/ide-diagnostics/src/handlers/unresolved_field.rs

+29-21
Original file line numberDiff line numberDiff line change
@@ -57,27 +57,34 @@ pub(crate) fn unresolved_field(
5757
}
5858

5959
fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Vec<Assist>> {
60-
let mut fixes = if d.method_with_same_name_exists { method_fix(ctx, &d.expr) } else { None };
61-
if let Some(fix) = add_field_fix(ctx, d) {
62-
fixes.get_or_insert_with(Vec::new).extend(fix);
60+
let mut fixes = Vec::new();
61+
if d.method_with_same_name_exists {
62+
fixes.extend(method_fix(ctx, &d.expr));
63+
}
64+
fixes.extend(field_fix(ctx, d));
65+
if fixes.is_empty() {
66+
None
67+
} else {
68+
Some(fixes)
6369
}
64-
fixes
6570
}
6671

67-
fn add_field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Vec<Assist>> {
72+
// FIXME: Add Snippet Support
73+
fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Assist> {
6874
// Get the FileRange of the invalid field access
6975
let root = ctx.sema.db.parse_or_expand(d.expr.file_id);
7076
let expr = d.expr.value.to_node(&root);
7177

7278
let error_range = ctx.sema.original_range_opt(expr.syntax())?;
79+
let field_name = d.name.as_str()?;
7380
// Convert the receiver to an ADT
74-
let adt = d.receiver.as_adt()?;
81+
let adt = d.receiver.strip_references().as_adt()?;
7582
let target_module = adt.module(ctx.sema.db);
7683

7784
let suggested_type =
7885
if let Some(new_field_type) = ctx.sema.type_of_expr(&expr).map(|v| v.adjusted()) {
7986
let display =
80-
new_field_type.display_source_code(ctx.sema.db, target_module.into(), true).ok();
87+
new_field_type.display_source_code(ctx.sema.db, target_module.into(), false).ok();
8188
make::ty(display.as_deref().unwrap_or("()"))
8289
} else {
8390
make::ty("()")
@@ -87,9 +94,6 @@ fn add_field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Opti
8794
return None;
8895
}
8996

90-
// FIXME: Add Snippet Support
91-
let field_name = d.name.as_str()?;
92-
9397
match adt {
9498
Adt::Struct(adt_struct) => {
9599
add_field_to_struct_fix(ctx, adt_struct, field_name, suggested_type, error_range)
@@ -100,13 +104,14 @@ fn add_field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Opti
100104
_ => None,
101105
}
102106
}
107+
103108
fn add_variant_to_union(
104109
ctx: &DiagnosticsContext<'_>,
105110
adt_union: Union,
106111
field_name: &str,
107112
suggested_type: Type,
108113
error_range: FileRange,
109-
) -> Option<Vec<Assist>> {
114+
) -> Option<Assist> {
110115
let adt_source = adt_union.source(ctx.sema.db)?;
111116
let adt_syntax = adt_source.syntax();
112117
let Some(field_list) = adt_source.value.record_field_list() else {
@@ -120,22 +125,23 @@ fn add_variant_to_union(
120125

121126
let mut src_change_builder = SourceChangeBuilder::new(range.file_id);
122127
src_change_builder.insert(offset, record_field);
123-
Some(vec![Assist {
128+
Some(Assist {
124129
id: AssistId("add-variant-to-union", AssistKind::QuickFix),
125130
label: Label::new("Add field to union".to_owned()),
126131
group: None,
127132
target: error_range.range,
128133
source_change: Some(src_change_builder.finish()),
129134
trigger_signature_help: false,
130-
}])
135+
})
131136
}
137+
132138
fn add_field_to_struct_fix(
133139
ctx: &DiagnosticsContext<'_>,
134140
adt_struct: Struct,
135141
field_name: &str,
136142
suggested_type: Type,
137143
error_range: FileRange,
138-
) -> Option<Vec<Assist>> {
144+
) -> Option<Assist> {
139145
let struct_source = adt_struct.source(ctx.sema.db)?;
140146
let struct_syntax = struct_source.syntax();
141147
let struct_range = struct_syntax.original_file_range(ctx.sema.db);
@@ -162,14 +168,14 @@ fn add_field_to_struct_fix(
162168

163169
// FIXME: Allow for choosing a visibility modifier see https://github.com/rust-lang/rust-analyzer/issues/11563
164170
src_change_builder.insert(offset, record_field);
165-
Some(vec![Assist {
171+
Some(Assist {
166172
id: AssistId("add-field-to-record-struct", AssistKind::QuickFix),
167173
label: Label::new("Add field to Record Struct".to_owned()),
168174
group: None,
169175
target: error_range.range,
170176
source_change: Some(src_change_builder.finish()),
171177
trigger_signature_help: false,
172-
}])
178+
})
173179
}
174180
None => {
175181
// Add a field list to the Unit Struct
@@ -193,21 +199,22 @@ fn add_field_to_struct_fix(
193199
}
194200
src_change_builder.replace(semi_colon.text_range(), record_field_list.to_string());
195201

196-
Some(vec![Assist {
202+
Some(Assist {
197203
id: AssistId("convert-unit-struct-to-record-struct", AssistKind::QuickFix),
198204
label: Label::new("Convert Unit Struct to Record Struct and add field".to_owned()),
199205
group: None,
200206
target: error_range.range,
201207
source_change: Some(src_change_builder.finish()),
202208
trigger_signature_help: false,
203-
}])
209+
})
204210
}
205211
Some(FieldList::TupleFieldList(_tuple)) => {
206212
// FIXME: Add support for Tuple Structs. Tuple Structs are not sent to this diagnostic
207213
None
208214
}
209215
}
210216
}
217+
211218
/// Used to determine the layout of the record field in the struct.
212219
fn record_field_layout(
213220
visibility: Option<Visibility>,
@@ -242,15 +249,16 @@ fn record_field_layout(
242249

243250
Some((offset, format!("{comma}{indent}{record_field}{trailing_new_line}")))
244251
}
252+
245253
// FIXME: We should fill out the call here, move the cursor and trigger signature help
246254
fn method_fix(
247255
ctx: &DiagnosticsContext<'_>,
248256
expr_ptr: &InFile<AstPtr<ast::Expr>>,
249-
) -> Option<Vec<Assist>> {
257+
) -> Option<Assist> {
250258
let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
251259
let expr = expr_ptr.value.to_node(&root);
252260
let FileRange { range, file_id } = ctx.sema.original_range_opt(expr.syntax())?;
253-
Some(vec![Assist {
261+
Some(Assist {
254262
id: AssistId("expected-field-found-method-call-fix", AssistKind::QuickFix),
255263
label: Label::new("Use parentheses to call the method".to_owned()),
256264
group: None,
@@ -260,7 +268,7 @@ fn method_fix(
260268
TextEdit::insert(range.end(), "()".to_owned()),
261269
)),
262270
trigger_signature_help: false,
263-
}])
271+
})
264272
}
265273
#[cfg(test)]
266274
mod tests {

0 commit comments

Comments
 (0)