diff options
Diffstat (limited to 'compiler')
43 files changed, 670 insertions, 619 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 89b59e5f00f..6dc459ea402 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -375,14 +375,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::Fn(..) => { - if self.sess.contains_name(&i.attrs[..], sym::plugin_registrar) { - gate_feature_post!( - &self, - plugin_registrar, - i.span, - "compiler plugins are experimental and possibly buggy" - ); - } if self.sess.contains_name(&i.attrs[..], sym::start) { gate_feature_post!( &self, diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 685f222e802..5d56c93f835 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -24,6 +24,7 @@ use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::Symbol; use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; +use smallvec::SmallVec; use std::cell::{Cell, RefCell}; use std::ffi::CStr; @@ -74,8 +75,12 @@ pub struct CodegenCx<'ll, 'tcx> { /// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details pub used_statics: RefCell<Vec<&'ll Value>>, - pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>, + /// Mapping of non-scalar types to llvm types and field remapping if needed. + pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>, + + /// Mapping of scalar types to llvm types. pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>, + pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, pub isize_ty: &'ll Type, @@ -92,6 +97,15 @@ pub struct CodegenCx<'ll, 'tcx> { local_gen_sym_counter: Cell<usize>, } +pub struct TypeLowering<'ll> { + /// Associated LLVM type + pub lltype: &'ll Type, + + /// If padding is used the slice maps fields from source order + /// to llvm order. + pub field_remapping: Option<SmallVec<[u32; 4]>>, +} + fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { match tls_model { TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic, @@ -304,7 +318,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { const_globals: Default::default(), statics_to_rauw: RefCell::new(Vec::new()), used_statics: RefCell::new(Vec::new()), - lltypes: Default::default(), + type_lowering: Default::default(), scalar_lltypes: Default::default(), pointee_infos: Default::default(), isize_ty, diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 52ae56b89b3..c7f4287e28e 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -266,7 +266,7 @@ impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { layout.is_llvm_scalar_pair() } fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 { - layout.llvm_field_index(index) + layout.llvm_field_index(self, index) } fn scalar_pair_element_backend_type( &self, diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 0876907e119..85efe3e6483 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,5 +1,6 @@ use crate::abi::FnAbi; use crate::common::*; +use crate::context::TypeLowering; use crate::type_::Type; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; @@ -9,6 +10,7 @@ use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape}; use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAndLayoutMethods, Variants}; +use smallvec::{smallvec, SmallVec}; use tracing::debug; use std::fmt::Write; @@ -17,6 +19,7 @@ fn uncached_llvm_type<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, layout: TyAndLayout<'tcx>, defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>, + field_remapping: &mut Option<SmallVec<[u32; 4]>>, ) -> &'a Type { match layout.abi { Abi::Scalar(_) => bug!("handled elsewhere"), @@ -75,7 +78,8 @@ fn uncached_llvm_type<'a, 'tcx>( FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count), FieldsShape::Arbitrary { .. } => match name { None => { - let (llfields, packed) = struct_llfields(cx, layout); + let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); + *field_remapping = new_field_remapping; cx.type_struct(&llfields, packed) } Some(ref name) => { @@ -90,7 +94,7 @@ fn uncached_llvm_type<'a, 'tcx>( fn struct_llfields<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, layout: TyAndLayout<'tcx>, -) -> (Vec<&'a Type>, bool) { +) -> (Vec<&'a Type>, bool, Option<SmallVec<[u32; 4]>>) { debug!("struct_llfields: {:#?}", layout); let field_count = layout.fields.count(); @@ -98,6 +102,7 @@ fn struct_llfields<'a, 'tcx>( let mut offset = Size::ZERO; let mut prev_effective_align = layout.align.abi; let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); + let mut field_remapping = smallvec![0; field_count]; for i in layout.fields.index_by_increasing_offset() { let target_offset = layout.fields.offset(i as usize); let field = layout.field(cx, i); @@ -116,33 +121,37 @@ fn struct_llfields<'a, 'tcx>( ); assert!(target_offset >= offset); let padding = target_offset - offset; - let padding_align = prev_effective_align.min(effective_field_align); - assert_eq!(offset.align_to(padding_align) + padding, target_offset); - result.push(cx.type_padding_filler(padding, padding_align)); - debug!(" padding before: {:?}", padding); - + if padding != Size::ZERO { + let padding_align = prev_effective_align.min(effective_field_align); + assert_eq!(offset.align_to(padding_align) + padding, target_offset); + result.push(cx.type_padding_filler(padding, padding_align)); + debug!(" padding before: {:?}", padding); + } + field_remapping[i] = result.len() as u32; result.push(field.llvm_type(cx)); offset = target_offset + field.size; prev_effective_align = effective_field_align; } + let padding_used = result.len() > field_count; if !layout.is_unsized() && field_count > 0 { if offset > layout.size { bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset); } let padding = layout.size - offset; - let padding_align = prev_effective_align; - assert_eq!(offset.align_to(padding_align) + padding, layout.size); - debug!( - "struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", - padding, offset, layout.size - ); - result.push(cx.type_padding_filler(padding, padding_align)); - assert_eq!(result.len(), 1 + field_count * 2); + if padding != Size::ZERO { + let padding_align = prev_effective_align; + assert_eq!(offset.align_to(padding_align) + padding, layout.size); + debug!( + "struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", + padding, offset, layout.size + ); + result.push(cx.type_padding_filler(padding, padding_align)); + } } else { debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size); } - - (result, packed) + let field_remapping = if padding_used { Some(field_remapping) } else { None }; + (result, packed, field_remapping) } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { @@ -177,7 +186,7 @@ pub trait LayoutLlvmExt<'tcx> { index: usize, immediate: bool, ) -> &'a Type; - fn llvm_field_index(&self, index: usize) -> u64; + fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64; fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo>; } @@ -234,8 +243,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { Variants::Single { index } => Some(index), _ => None, }; - if let Some(&llty) = cx.lltypes.borrow().get(&(self.ty, variant_index)) { - return llty; + if let Some(ref llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { + return llty.lltype; } debug!("llvm_type({:#?})", self); @@ -247,6 +256,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { let normal_ty = cx.tcx.erase_regions(self.ty); let mut defer = None; + let mut field_remapping = None; let llty = if self.ty != normal_ty { let mut layout = cx.layout_of(normal_ty); if let Some(v) = variant_index { @@ -254,17 +264,24 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { } layout.llvm_type(cx) } else { - uncached_llvm_type(cx, *self, &mut defer) + uncached_llvm_type(cx, *self, &mut defer, &mut field_remapping) }; debug!("--> mapped {:#?} to llty={:?}", self, llty); - cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty); + cx.type_lowering.borrow_mut().insert( + (self.ty, variant_index), + TypeLowering { lltype: llty, field_remapping: field_remapping }, + ); if let Some((llty, layout)) = defer { - let (llfields, packed) = struct_llfields(cx, layout); - cx.set_struct_body(llty, &llfields, packed) + let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); + cx.set_struct_body(llty, &llfields, packed); + cx.type_lowering + .borrow_mut() + .get_mut(&(self.ty, variant_index)) + .unwrap() + .field_remapping = new_field_remapping; } - llty } @@ -340,7 +357,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { self.scalar_llvm_type_at(cx, scalar, offset) } - fn llvm_field_index(&self, index: usize) -> u64 { + fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 { match self.abi { Abi::Scalar(_) | Abi::ScalarPair(..) => { bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self) @@ -354,7 +371,25 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { FieldsShape::Array { .. } => index as u64, - FieldsShape::Arbitrary { .. } => 1 + (self.fields.memory_index(index) as u64) * 2, + FieldsShape::Arbitrary { .. } => { + let variant_index = match self.variants { + Variants::Single { index } => Some(index), + _ => None, + }; + + // Look up llvm field if indexes do not match memory order due to padding. If + // `field_remapping` is `None` no padding was used and the llvm field index + // matches the memory index. + match cx.type_lowering.borrow().get(&(self.ty, variant_index)) { + Some(TypeLowering { field_remapping: Some(ref remap), .. }) => { + remap[index] as u64 + } + Some(_) => self.fields.memory_index(index) as u64, + None => { + bug!("TyAndLayout::llvm_field_index({:?}): type info not found", self) + } + } + } } } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index c9fb09570c3..2208ec37a42 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -98,7 +98,8 @@ fn emit_aapcs_va_arg( // Implementation of the AAPCS64 calling convention for va_args see // https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst let va_list_addr = list.immediate(); - let va_list_ty = list.deref(bx.cx).layout.llvm_type(bx); + let va_list_layout = list.deref(bx.cx).layout; + let va_list_ty = va_list_layout.llvm_type(bx); let layout = bx.cx.layout_of(target_ty); let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg"); @@ -110,13 +111,15 @@ fn emit_aapcs_va_arg( let gr_type = target_ty.is_any_ptr() || target_ty.is_integral(); let (reg_off, reg_top_index, slot_size) = if gr_type { - let gr_offs = bx.struct_gep(va_list_ty, va_list_addr, 7); + let gr_offs = + bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 3)); let nreg = (layout.size.bytes() + 7) / 8; - (gr_offs, 3, nreg * 8) + (gr_offs, va_list_layout.llvm_field_index(bx.cx, 1), nreg * 8) } else { - let vr_off = bx.struct_gep(va_list_ty, va_list_addr, 9); + let vr_off = + bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 4)); let nreg = (layout.size.bytes() + 15) / 16; - (vr_off, 5, nreg * 16) + (vr_off, va_list_layout.llvm_field_index(bx.cx, 2), nreg * 16) }; // if the offset >= 0 then the value will be on the stack diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 4ef21449d21..4a7090b31b4 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -137,10 +137,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap< reachable_non_generics.insert(id.to_def_id(), SymbolExportLevel::C); } - if let Some(id) = tcx.plugin_registrar_fn(()) { - reachable_non_generics.insert(id.to_def_id(), SymbolExportLevel::C); - } - reachable_non_generics } diff --git a/compiler/rustc_data_structures/src/graph/mod.rs b/compiler/rustc_data_structures/src/graph/mod.rs index e0903e43241..dff22855629 100644 --- a/compiler/rustc_data_structures/src/graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/mod.rs @@ -60,18 +60,13 @@ pub trait WithStartNode: DirectedGraph { } pub trait ControlFlowGraph: - DirectedGraph + WithStartNode + WithPredecessors + WithStartNode + WithSuccessors + WithNumNodes + DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes { // convenient trait } impl<T> ControlFlowGraph for T where - T: DirectedGraph - + WithStartNode - + WithPredecessors - + WithStartNode - + WithSuccessors - + WithNumNodes + T: DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes { } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 84dd69ebd96..fcc70b2e4c5 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1287,9 +1287,6 @@ pub fn init_env_logger(env: &str) { .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) - .with_wraparound(10) - .with_verbose_exit(true) - .with_verbose_entry(true) .with_indent_amount(2); #[cfg(parallel_compiler)] let layer = layer.with_thread_ids(true).with_thread_names(true); diff --git a/compiler/rustc_error_codes/src/error_codes/E0530.md b/compiler/rustc_error_codes/src/error_codes/E0530.md index 502f674fc1d..60fa711cbed 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0530.md +++ b/compiler/rustc_error_codes/src/error_codes/E0530.md @@ -1,32 +1,57 @@ A binding shadowed something it shouldn't. -Erroneous code example: +A match arm or a variable has a name that is already used by +something else, e.g. + +* struct name +* enum variant +* static +* associated constant + +This error may also happen when an enum variant *with fields* is used +in a pattern, but without its fields. + +```compile_fail +enum Enum { + WithField(i32) +} + +use Enum::*; +match WithField(1) { + WithField => {} // error: missing (_) +} +``` + +Match bindings cannot shadow statics: ```compile_fail,E0530 static TEST: i32 = 0; -let r: (i32, i32) = (0, 0); +let r = 123; match r { - TEST => {} // error: match bindings cannot shadow statics + TEST => {} // error: name of a static } ``` -To fix this error, just change the binding's name in order to avoid shadowing -one of the following: +Fixed examples: -* struct name -* struct/enum variant -* static -* const -* associated const +``` +static TEST: i32 = 0; -Fixed example: +let r = 123; +match r { + some_value => {} // ok! +} +``` + +or ``` -static TEST: i32 = 0; +const TEST: i32 = 0; // const, not static -let r: (i32, i32) = (0, 0); +let r = 123; match r { - something => {} // ok! + TEST => {} // const is ok! + other_values => {} } ``` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 050f3ae5833..07c864c93a1 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -14,7 +14,10 @@ use rustc_span::{MultiSpan, SourceFile, Span}; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; use crate::styled_buffer::StyledBuffer; -use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle}; +use crate::{ + CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SubstitutionHighlight, + SuggestionStyle, +}; use rustc_lint_defs::pluralize; @@ -1590,8 +1593,11 @@ impl EmitterWriter { ); let mut row_num = 2; + draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); let mut notice_capitalization = false; - for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) { + for (complete, parts, highlights, only_capitalization) in + suggestions.iter().take(MAX_SUGGESTIONS) + { notice_capitalization |= only_capitalization; // Only show underline if the suggestion spans a single line and doesn't cover the // entirety of the code output. If you have multiple replacements in the same line @@ -1599,16 +1605,26 @@ impl EmitterWriter { let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim()) && complete.lines().count() == 1; - let lines = sm + let has_deletion = parts.iter().any(|p| p.is_deletion()); + let is_multiline = complete.lines().count() > 1; + + let show_diff = has_deletion && !is_multiline; + + if show_diff { + row_num += 1; + } + + let file_lines = sm .span_to_lines(parts[0].span) .expect("span_to_lines failed when emitting suggestion"); - assert!(!lines.lines.is_empty() || parts[0].span.is_dummy()); + assert!(!file_lines.lines.is_empty() || parts[0].span.is_dummy()); let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); let mut lines = complete.lines(); - for (line_pos, line) in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate() + for (line_pos, (line, parts)) in + lines.by_ref().zip(highlights).take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate() { // Print the span column to avoid confusion buffer.puts( @@ -1617,9 +1633,60 @@ impl EmitterWriter { &self.maybe_anonymized(line_start + line_pos), Style::LineNumber, ); + if show_diff { + // Add the line number for both addition and removal to drive the point home. + // + // N - fn foo<A: T>(bar: A) { + // N + fn foo(bar: impl T) { + buffer.puts( + row_num - 1, + 0, + &self.maybe_anonymized(line_start + line_pos), + Style::LineNumber, + ); + buffer.puts(row_num - 1, max_line_num_len + 1, "- ", Style::Removal); + buffer.puts( + row_num - 1, + max_line_num_len + 3, + &replace_tabs( + &*file_lines + .file + .get_line(file_lines.lines[line_pos].line_index) + .unwrap(), + ), + Style::NoStyle, + ); + buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition); + } else if is_multiline { + match &parts[..] { + [SubstitutionHighlight { start: 0, end }] if *end == line.len() => { + buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition); + } + [] => { + draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); + } + _ => { + buffer.puts(row_num, max_line_num_len + 1, "~ ", Style::Addition); + } + } + } else { + draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); + } + // print the suggestion - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); buffer.append(row_num, &replace_tabs(line), Style::NoStyle); + + if is_multiline { + for SubstitutionHighlight { start, end } in parts { + buffer.set_style_range( + row_num, + max_line_num_len + 3 + start, + max_line_num_len + 3 + end, + Style::Addition, + true, + ); + } + } row_num += 1; } @@ -1654,25 +1721,36 @@ impl EmitterWriter { let underline_start = (span_start_pos + start) as isize + offset; let underline_end = (span_start_pos + start + sub_len) as isize + offset; assert!(underline_start >= 0 && underline_end >= 0); + let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { - buffer.putc( - row_num, - ((max_line_num_len + 3) as isize + p) as usize, - '^', - Style::UnderlinePrimary, + // Colorize addition/replacements with green. + buffer.set_style( + row_num - 1, + (padding as isize + p) as usize, + Style::Addition, + true, ); - } - // underline removals too - if underline_start == underline_end { - for p in underline_start - 1..underline_start + 1 { + if !show_diff { + // If this is a replacement, underline with `^`, if this is an addition + // underline with `+`. buffer.putc( row_num, - ((max_line_num_len + 3) as isize + p) as usize, - '-', - Style::UnderlineSecondary, + (padding as isize + p) as usize, + if part.is_addition(&sm) { '+' } else { '~' }, + Style::Addition, ); } } + if show_diff { + // Colorize removal with red in diff format. + buffer.set_style_range( + row_num - 2, + (padding as isize + span_start_pos as isize) as usize, + (padding as isize + span_end_pos as isize) as usize, + Style::Removal, + true, + ); + } // length of the code after substitution let full_sub_len = part @@ -2129,6 +2207,12 @@ impl<'a> WritableDst<'a> { fn apply_style(&mut self, lvl: Level, style: Style) -> io::Result<()> { let mut spec = ColorSpec::new(); match style { + Style::Addition => { + spec.set_fg(Some(Color::Green)).set_intense(true); + } + Style::Removal => { + spec.set_fg(Some(Color::Red)).set_intense(true); + } Style::LineAndColumn => {} Style::LineNumber => { spec.set_bold(true); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fc0924ac5f9..ec29d8016dd 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -160,32 +160,77 @@ pub struct SubstitutionPart { pub snippet: String, } +/// Used to translate between `Span`s and byte positions within a single output line in highlighted +/// code of structured suggestions. +#[derive(Debug, Clone, Copy)] +pub struct SubstitutionHighlight { + start: usize, + end: usize, +} + +impl SubstitutionPart { + pub fn is_addition(&self, sm: &SourceMap) -> bool { + !self.snippet.is_empty() + && sm + .span_to_snippet(self.span) + .map_or(self.span.is_empty(), |snippet| snippet.trim().is_empty()) + } + + pub fn is_deletion(&self) -> bool { + self.snippet.trim().is_empty() + } + + pub fn is_replacement(&self, sm: &SourceMap) -> bool { + !self.snippet.is_empty() + && sm + .span_to_snippet(self.span) + .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty()) + } +} + impl CodeSuggestion { /// Returns the assembled code suggestions, whether they should be shown with an underline /// and whether the substitution only differs in capitalization. - pub fn splice_lines(&self, sm: &SourceMap) -> Vec<(String, Vec<SubstitutionPart>, bool)> { + pub fn splice_lines( + &self, + sm: &SourceMap, + ) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, bool)> { + // For the `Vec<Vec<SubstitutionHighlight>>` value, the first level of the vector + // corresponds to the output snippet's lines, while the second level corresponds to the + // substrings within that line that should be highlighted. + use rustc_span::{CharPos, Pos}; + /// Append to a buffer the remainder of the line of existing source code, and return the + /// count of lines that have been added for accurate highlighting. fn push_trailing( buf: &mut String, line_opt: Option<&Cow<'_, str>>, lo: &Loc, hi_opt: Option<&Loc>, - ) { + ) -> usize { + let mut line_count = 0; let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); match hi_opt { - Some(hi) if hi > lo => buf.push_str(&line[lo..hi]), + Some(hi) if hi > lo => { + line_count = line[lo..hi].matches('\n').count(); + buf.push_str(&line[lo..hi]) + } Some(_) => (), - None => buf.push_str(&line[lo..]), + None => { + line_count = line[lo..].matches('\n').count(); + buf.push_str(&line[lo..]) + } } } if hi_opt.is_none() { buf.push('\n'); } } + line_count } assert!(!self.substitutions.is_empty()); @@ -220,6 +265,7 @@ impl CodeSuggestion { return None; } + let mut highlights = vec![]; // To build up the result, we do this for each span: // - push the line segment trailing the previous span // (at the beginning a "phantom" span pointing at the start of the line) @@ -236,17 +282,29 @@ impl CodeSuggestion { lines.lines.get(0).and_then(|line0| sf.get_line(line0.line_index)); let mut buf = String::new(); + let mut line_highlight = vec![]; for part in &substitution.parts { let cur_lo = sm.lookup_char_pos(part.span.lo()); if prev_hi.line == cur_lo.line { - push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); + let mut count = + push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); + while count > 0 { + highlights.push(std::mem::take(&mut line_highlight)); + count -= 1; + } } else { - push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None); + highlights.push(std::mem::take(&mut line_highlight)); + let mut count = push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None); + while count > 0 { + highlights.push(std::mem::take(&mut line_highlight)); + count -= 1; + } // push lines between the previous and current span (if any) for idx in prev_hi.line..(cur_lo.line - 1) { if let Some(line) = sf.get_line(idx) { buf.push_str(line.as_ref()); buf.push('\n'); + highlights.push(std::mem::take(&mut line_highlight)); } } if let Some(cur_line) = sf.get_line(cur_lo.line - 1) { @@ -257,10 +315,21 @@ impl CodeSuggestion { buf.push_str(&cur_line[..end]); } } + // Add a whole line highlight per line in the snippet. + line_highlight.push(SubstitutionHighlight { + start: cur_lo.col.0, + end: cur_lo.col.0 + + part.snippet.split('\n').next().unwrap_or(&part.snippet).len(), + }); + for line in part.snippet.split('\n').skip(1) { + highlights.push(std::mem::take(&mut line_highlight)); + line_highlight.push(SubstitutionHighlight { start: 0, end: line.len() }); + } buf.push_str(&part.snippet); prev_hi = sm.lookup_char_pos(part.span.hi()); prev_line = sf.get_line(prev_hi.line - 1); } + highlights.push(std::mem::take(&mut line_highlight)); let only_capitalization = is_case_difference(sm, &buf, bounding_span); // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { @@ -270,7 +339,7 @@ impl CodeSuggestion { while buf.ends_with('\n') { buf.pop(); } - Some((buf, substitution.parts, only_capitalization)) + Some((buf, substitution.parts, highlights, only_capitalization)) }) .collect() } diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 3fe02bd0cee..64353461e90 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -177,4 +177,6 @@ pub enum Style { NoStyle, Level(Level), Highlight, + Addition, + Removal, } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 128b51c2061..73b29d65e91 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -281,9 +281,6 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using `#[plugin_registrar]` on functions. - (active, plugin_registrar, "1.0.0", Some(29597), None), - /// Allows using `#![plugin(myplugin)]`. (active, plugin, "1.0.0", Some(29597), None), diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 49cca3fbc39..5729384c0da 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -292,18 +292,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Plugins: ( - sym::plugin_registrar, Normal, template!(Word), - Gated( - Stability::Deprecated( - "https://github.com/rust-lang/rust/pull/64675", - Some("may be removed in a future compiler version"), - ), - sym::plugin_registrar, - "compiler plugins are deprecated", - cfg_fn!(plugin_registrar) - ) - ), - ( sym::plugin, CrateLevel, template!(List: "name"), Gated( Stability::Deprecated( diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 46b36f2b704..5cadbd9e5cf 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -136,9 +136,12 @@ declare_features! ( (removed, main, "1.53.0", Some(29634), None, None), (removed, pub_macro_rules, "1.53.0", Some(78855), None, Some("removed due to being incomplete, in particular it does not work across crates")), - /// Allows the definition of `const` functions with some advanced features. + /// Allows the definition of `const` functions with some advanced features. (removed, const_fn, "1.54.0", Some(57563), None, Some("split into finer-grained feature gates")), + /// Allows using `#[plugin_registrar]` on functions. + (removed, plugin_registrar, "1.54.0", Some(29597), None, + Some("a __rustc_plugin_registrar symbol must now be defined instead")), /// Allows `#[doc(include = "some-file")]`. (removed, external_doc, "1.54.0", Some(44732), None, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f0d63f512fc..10217a5f574 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -4,10 +4,12 @@ pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; +use self::opaque_types::OpaqueTypeMap; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; +use hir::def_id::CRATE_DEF_ID; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; @@ -59,6 +61,7 @@ pub mod lattice; mod lexical_region_resolve; mod lub; pub mod nll_relate; +pub mod opaque_types; pub mod outlives; pub mod region_constraints; pub mod resolve; @@ -191,6 +194,19 @@ pub struct InferCtxtInner<'tcx> { region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>, undo_log: InferCtxtUndoLogs<'tcx>, + + // Opaque types found in explicit return types and their + // associated fresh inference variable. Writeback resolves these + // variables to get the concrete type, which can be used to + // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions. + pub opaque_types: OpaqueTypeMap<'tcx>, + + /// A map from inference variables created from opaque + /// type instantiations (`ty::Infer`) to the actual opaque + /// type (`ty::Opaque`). Used during fallback to map unconstrained + /// opaque type inference variables to their corresponding + /// opaque type. + pub opaque_types_vars: FxHashMap<Ty<'tcx>, Ty<'tcx>>, } impl<'tcx> InferCtxtInner<'tcx> { @@ -204,6 +220,8 @@ impl<'tcx> InferCtxtInner<'tcx> { float_unification_storage: ut::UnificationTableStorage::new(), region_constraint_storage: Some(RegionConstraintStorage::new()), region_obligations: vec![], + opaque_types: Default::default(), + opaque_types_vars: Default::default(), } } @@ -273,6 +291,10 @@ impl<'tcx> InferCtxtInner<'tcx> { pub struct InferCtxt<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, + /// The `DefId` of the item in whose context we are performing inference or typeck. + /// It is used to check whether an opaque type use is a defining use. + pub defining_use_anchor: LocalDefId, + /// During type-checking/inference of a body, `in_progress_typeck_results` /// contains a reference to the typeck results being built up, which are /// used for reading closure kinds/signatures as they are inferred, @@ -531,6 +553,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> { pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>, + defining_use_anchor: LocalDefId, } pub trait TyCtxtInferExt<'tcx> { @@ -539,15 +562,31 @@ pub trait TyCtxtInferExt<'tcx> { impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { - InferCtxtBuilder { tcx: self, fresh_typeck_results: None } + InferCtxtBuilder { + tcx: self, + defining_use_anchor: CRATE_DEF_ID, + fresh_typeck_results: None, + } } } impl<'tcx> InferCtxtBuilder<'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_typeck_results` with fresh `TypeckResults`. + /// Will also change the scope for opaque type defining use checks to the given owner. pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self { self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner))); + self.with_opaque_type_inference(table_owner) + } + + /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, + /// you need to call this function. Otherwise the opaque type will be treated opaquely. + /// + /// It is only meant to be called in two places, for typeck + /// (via `with_fresh_in_progress_typeck_results`) and for the inference context used + /// in mir borrowck. + pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self { + self.defining_use_anchor = defining_use_anchor; self } @@ -575,10 +614,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R { - let InferCtxtBuilder { tcx, ref fresh_typeck_results } = *self; + let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self; let in_progress_typeck_results = fresh_typeck_results.as_ref(); f(InferCtxt { tcx, + defining_use_anchor, in_progress_typeck_results, inner: RefCell::new(InferCtxtInner::new()), lexical_region_resolutions: RefCell::new(None), diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs new file mode 100644 index 00000000000..d0883f23a4e --- /dev/null +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -0,0 +1,47 @@ +use rustc_data_structures::vec_map::VecMap; +use rustc_hir as hir; +use rustc_middle::ty::{OpaqueTypeKey, Ty}; +use rustc_span::Span; + +pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>; + +/// Information about the opaque types whose values we +/// are inferring in this function (these are the `impl Trait` that +/// appear in the return type). +#[derive(Copy, Clone, Debug)] +pub struct OpaqueTypeDecl<'tcx> { + /// The opaque type (`ty::Opaque`) for this declaration. + pub opaque_type: Ty<'tcx>, + + /// The span of this particular definition of the opaque type. So + /// for example: + /// + /// ```ignore (incomplete snippet) + /// type Foo = impl Baz; + /// fn bar() -> Foo { + /// // ^^^ This is the span we are looking for! + /// } + /// ``` + /// + /// In cases where the fn returns `(impl Trait, impl Trait)` or + /// other such combinations, the result is currently + /// over-approximated, but better than nothing. + pub definition_span: Span, + + /// The type variable that represents the value of the opaque type + /// that we require. In other words, after we compile this function, + /// we will be created a constraint like: + /// + /// Foo<'a, T> = ?C + /// + /// where `?C` is the value of this type variable. =) It may + /// naturally refer to the type and lifetime parameters in scope + /// in this function, though ultimately it should only reference + /// those that are arguments to `Foo` in the constraint above. (In + /// other words, `?C` should not include `'b`, even though it's a + /// lifetime parameter on `foo`.) + pub concrete_ty: Ty<'tcx>, + + /// The origin of the opaque type. + pub origin: hir::OpaqueTyOrigin, +} diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5db027fb5b4..5dc57f6023b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -741,7 +741,6 @@ pub static DEFAULT_QUERY_PROVIDERS: SyncLazy<Providers> = SyncLazy::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; proc_macro_decls::provide(providers); - plugin::build::provide(providers); rustc_middle::hir::provide(providers); mir::provide(providers); mir_build::provide(providers); @@ -856,8 +855,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { { entry_point = sess.time("looking_for_entry_point", || tcx.entry_fn(())); - sess.time("looking_for_plugin_registrar", || tcx.ensure().plugin_registrar_fn(())); - sess.time("looking_for_derive_registrar", || { tcx.ensure().proc_macro_decls_static(()) }); diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 9a96c03cd3c..b970c9e4911 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -60,6 +60,9 @@ pub enum EscapeError { /// After a line ending with '\', the next line contains whitespace /// characters that are not skipped. UnskippedWhitespaceWarning, + + /// After a line ending with '\', multiple lines are skipped. + MultipleSkippedLinesWarning, } impl EscapeError { @@ -67,6 +70,7 @@ impl EscapeError { pub fn is_fatal(&self) -> bool { match self { EscapeError::UnskippedWhitespaceWarning => false, + EscapeError::MultipleSkippedLinesWarning => false, _ => true, } } @@ -315,12 +319,17 @@ where where F: FnMut(Range<usize>, Result<char, EscapeError>), { - let str = chars.as_str(); - let first_non_space = str + let tail = chars.as_str(); + let first_non_space = tail .bytes() .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r') - .unwrap_or(str.len()); - let tail = &str[first_non_space..]; + .unwrap_or(tail.len()); + if tail[1..first_non_space].contains('\n') { + // The +1 accounts for the escaping slash. + let end = start + first_non_space + 1; + callback(start..end, Err(EscapeError::MultipleSkippedLinesWarning)); + } + let tail = &tail[first_non_space..]; if let Some(c) = tail.chars().nth(0) { // For error reporting, we would like the span to contain the character that was not // skipped. The +1 is necessary to account for the leading \ that started the escape. diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index 1f4dbb20f4e..fa61554afde 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -106,6 +106,10 @@ fn test_unescape_str_warn() { assert_eq!(unescaped, expected); } + // Check we can handle escaped newlines at the end of a file. + check("\\\n", &[]); + check("\\\n ", &[]); + check( "\\\n \u{a0} x", &[ @@ -115,6 +119,7 @@ fn test_unescape_str_warn() { (6..7, Ok('x')), ], ); + check("\\\n \n x", &[(0..7, Err(EscapeError::MultipleSkippedLinesWarning)), (7..8, Ok('x'))]); } #[test] diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index cf8577a26cf..8d1bf6f55df 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -226,7 +226,7 @@ use rustc_session::config::{self, CrateType}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; -use rustc_session::{Session, StableCrateId}; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -787,7 +787,7 @@ pub fn find_plugin_registrar( metadata_loader: &dyn MetadataLoader, span: Span, name: Symbol, -) -> (PathBuf, StableCrateId) { +) -> PathBuf { match find_plugin_registrar_impl(sess, metadata_loader, name) { Ok(res) => res, // `core` is always available if we got as far as loading plugins. @@ -799,7 +799,7 @@ fn find_plugin_registrar_impl<'a>( sess: &'a Session, metadata_loader: &dyn MetadataLoader, name: Symbol, -) -> Result<(PathBuf, StableCrateId), CrateError> { +) -> Result<PathBuf, CrateError> { info!("find plugin registrar `{}`", name); let mut locator = CrateLocator::new( sess, @@ -816,7 +816,7 @@ fn find_plugin_registrar_impl<'a>( match locator.maybe_load_library_crate()? { Some(library) => match library.source.dylib { - Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())), + Some(dylib) => Ok(dylib.0), None => Err(CrateError::NonDylibPlugin(name)), }, None => Err(locator.into_error()), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 3c16852df05..7c7025ac37a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1252,9 +1252,6 @@ rustc_queries! { query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { desc { "looking up the entry function of a crate" } } - query plugin_registrar_fn(_: ()) -> Option<LocalDefId> { - desc { "looking up the plugin registrar for a crate" } - } query proc_macro_decls_static(_: ()) -> Option<LocalDefId> { desc { "looking up the derive registrar for a crate" } } diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 36eb8a4baa8..2bfa51f27bb 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -105,7 +105,7 @@ fn mir_borrowck<'tcx>( let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); - let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { + let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); do_mir_borrowck(&infcx, input_body, promoted) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 3fb06cd2f5f..f69d08a6d59 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -179,54 +179,55 @@ pub(crate) fn type_check<'mir, 'tcx>( liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); translate_outlives_facts(&mut cx); - let mut opaque_type_values = cx.opaque_type_values; - - for (_, revealed_ty) in &mut opaque_type_values { - *revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty); - if revealed_ty.has_infer_types_or_consts() { - infcx.tcx.sess.delay_span_bug( - body.span, - &format!("could not resolve {:#?}", revealed_ty.kind()), - ); - *revealed_ty = infcx.tcx.ty_error(); - } - } - - opaque_type_values.retain(|(opaque_type_key, resolved_ty)| { - let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { - *def_id == opaque_type_key.def_id - } else { - false - }; + let opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types); - if concrete_is_opaque { - // We're using an opaque `impl Trait` type without - // 'revealing' it. For example, code like this: - // - // type Foo = impl Debug; - // fn foo1() -> Foo { ... } - // fn foo2() -> Foo { foo1() } - // - // In `foo2`, we're not revealing the type of `Foo` - we're - // just treating it as the opaque type. - // - // When this occurs, we do *not* want to try to equate - // the concrete type with the underlying defining type - // of the opaque type - this will always fail, since - // the defining type of an opaque type is always - // some other type (e.g. not itself) - // Essentially, none of the normal obligations apply here - - // we're just passing around some unknown opaque type, - // without actually looking at the underlying type it - // gets 'revealed' into - debug!( - "eq_opaque_type_and_type: non-defining use of {:?}", - opaque_type_key.def_id, - ); - } - !concrete_is_opaque - }); opaque_type_values + .into_iter() + .filter_map(|(opaque_type_key, decl)| { + let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty); + if revealed_ty.has_infer_types_or_consts() { + infcx.tcx.sess.delay_span_bug( + body.span, + &format!("could not resolve {:#?}", revealed_ty.kind()), + ); + revealed_ty = infcx.tcx.ty_error(); + } + let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() { + *def_id == opaque_type_key.def_id + } else { + false + }; + + if concrete_is_opaque { + // We're using an opaque `impl Trait` type without + // 'revealing' it. For example, code like this: + // + // type Foo = impl Debug; + // fn foo1() -> Foo { ... } + // fn foo2() -> Foo { foo1() } + // + // In `foo2`, we're not revealing the type of `Foo` - we're + // just treating it as the opaque type. + // + // When this occurs, we do *not* want to try to equate + // the concrete type with the underlying defining type + // of the opaque type - this will always fail, since + // the defining type of an opaque type is always + // some other type (e.g. not itself) + // Essentially, none of the normal obligations apply here - + // we're just passing around some unknown opaque type, + // without actually looking at the underlying type it + // gets 'revealed' into + debug!( + "eq_opaque_type_and_type: non-defining use of {:?}", + opaque_type_key.def_id, + ); + None + } else { + Some((opaque_type_key, revealed_ty)) + } + }) + .collect() }, ); @@ -865,7 +866,6 @@ struct TypeChecker<'a, 'tcx> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, universal_region_relations: &'a UniversalRegionRelations<'tcx>, - opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>, } struct BorrowCheckContext<'a, 'tcx> { @@ -1025,7 +1025,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { borrowck_context, reported_errors: Default::default(), universal_region_relations, - opaque_type_values: VecMap::default(), }; checker.check_user_type_annotations(); checker @@ -1289,10 +1288,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let body = self.body; let mir_def_id = body.source.def_id().expect_local(); - let mut opaque_type_values = VecMap::new(); - debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id); - let opaque_type_map = self.fully_perform_op( + self.fully_perform_op( locations, category, CustomTypeOp::new( @@ -1307,20 +1304,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`. // (Note that the key of the map is both the def-id of `Foo` along with // any generic parameters.) - let (output_ty, opaque_type_map) = - obligations.add(infcx.instantiate_opaque_types( - mir_def_id, - dummy_body_id, - param_env, - anon_ty, - locations.span(body), - )); + let output_ty = obligations.add(infcx.instantiate_opaque_types( + dummy_body_id, + param_env, + anon_ty, + locations.span(body), + )); debug!( "eq_opaque_type_and_type: \ instantiated output_ty={:?} \ - opaque_type_map={:#?} \ revealed_ty={:?}", - output_ty, opaque_type_map, revealed_ty + output_ty, revealed_ty ); // Make sure that the inferred types are well-formed. I'm @@ -1338,48 +1332,38 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .eq(output_ty, revealed_ty)?, ); - for &(opaque_type_key, opaque_decl) in &opaque_type_map { - opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty); - } - debug!("eq_opaque_type_and_type: equated"); - Ok(InferOk { - value: Some(opaque_type_map), - obligations: obligations.into_vec(), - }) + Ok(InferOk { value: (), obligations: obligations.into_vec() }) }, || "input_output".to_string(), ), )?; - self.opaque_type_values.extend(opaque_type_values); - let universal_region_relations = self.universal_region_relations; // Finally, if we instantiated the anon types successfully, we // have to solve any bounds (e.g., `-> impl Iterator` needs to // prove that `T: Iterator` where `T` is the type we // instantiated it with). - if let Some(opaque_type_map) = opaque_type_map { - for (opaque_type_key, opaque_decl) in opaque_type_map { - self.fully_perform_op( - locations, - ConstraintCategory::OpaqueType, - CustomTypeOp::new( - |infcx| { - infcx.constrain_opaque_type( - opaque_type_key, - &opaque_decl, - GenerateMemberConstraints::IfNoStaticBound, - universal_region_relations, - ); - Ok(InferOk { value: (), obligations: vec![] }) - }, - || "opaque_type_map".to_string(), - ), - )?; - } + let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone(); + for (opaque_type_key, opaque_decl) in opaque_type_map { + self.fully_perform_op( + locations, + ConstraintCategory::OpaqueType, + CustomTypeOp::new( + |infcx| { + infcx.constrain_opaque_type( + opaque_type_key, + &opaque_decl, + GenerateMemberConstraints::IfNoStaticBound, + universal_region_relations, + ); + Ok(InferOk { value: (), obligations: vec![] }) + }, + || "opaque_type_map".to_string(), + ), + )?; } Ok(()) } diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 4e95cdc0efa..aa6b424ce2b 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -280,6 +280,11 @@ pub(crate) fn emit_unescape_error( format!("non-ASCII whitespace symbol '{}' is not skipped", c.escape_unicode()); handler.struct_span_warn(span, &msg).span_label(char_span, &msg).emit(); } + EscapeError::MultipleSkippedLinesWarning => { + let msg = "multiple lines skipped by escaped newline"; + let bottom_msg = "skipping everything up to and including this point"; + handler.struct_span_warn(span, msg).span_label(span, bottom_msg).emit(); + } } } diff --git a/compiler/rustc_plugin_impl/src/build.rs b/compiler/rustc_plugin_impl/src/build.rs deleted file mode 100644 index b95c4a72019..00000000000 --- a/compiler/rustc_plugin_impl/src/build.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! Used by `rustc` when compiling a plugin crate. - -use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; -use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::ty::query::Providers; -use rustc_middle::ty::TyCtxt; -use rustc_span::symbol::sym; -use rustc_span::Span; - -struct RegistrarFinder<'tcx> { - tcx: TyCtxt<'tcx>, - registrars: Vec<(LocalDefId, Span)>, -} - -impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> { - fn visit_item(&mut self, item: &hir::Item<'_>) { - if let hir::ItemKind::Fn(..) = item.kind { - let attrs = self.tcx.hir().attrs(item.hir_id()); - if self.tcx.sess.contains_name(attrs, sym::plugin_registrar) { - self.registrars.push((item.def_id, item.span)); - } - } - } - - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} - - fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} -} - -/// Finds the function marked with `#[plugin_registrar]`, if any. -fn plugin_registrar_fn(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { - let mut finder = RegistrarFinder { tcx, registrars: Vec::new() }; - tcx.hir().krate().visit_all_item_likes(&mut finder); - - let (def_id, span) = finder.registrars.pop()?; - - if !finder.registrars.is_empty() { - let diagnostic = tcx.sess.diagnostic(); - let mut e = diagnostic.struct_err("multiple plugin registration functions found"); - e.span_note(span, "one is here"); - for &(_, span) in &finder.registrars { - e.span_note(span, "one is here"); - } - e.emit(); - diagnostic.abort_if_errors(); - unreachable!(); - } - - Some(def_id) -} - -pub fn provide(providers: &mut Providers) { - *providers = Providers { plugin_registrar_fn, ..*providers }; -} diff --git a/compiler/rustc_plugin_impl/src/lib.rs b/compiler/rustc_plugin_impl/src/lib.rs index 5bf4d300e9e..a1e13a1abb6 100644 --- a/compiler/rustc_plugin_impl/src/lib.rs +++ b/compiler/rustc_plugin_impl/src/lib.rs @@ -12,7 +12,6 @@ use rustc_lint::LintStore; -pub mod build; pub mod load; /// Structure used to register plugins. diff --git a/compiler/rustc_plugin_impl/src/load.rs b/compiler/rustc_plugin_impl/src/load.rs index 687f7db221f..5da02e3a489 100644 --- a/compiler/rustc_plugin_impl/src/load.rs +++ b/compiler/rustc_plugin_impl/src/load.rs @@ -55,20 +55,13 @@ fn load_plugin( metadata_loader: &dyn MetadataLoader, ident: Ident, ) { - let (lib, disambiguator) = - locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); - let symbol = sess.generate_plugin_registrar_symbol(disambiguator); - let fun = dylink_registrar(sess, ident.span, lib, symbol); + let lib = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); + let fun = dylink_registrar(sess, ident.span, lib); plugins.push(fun); } // Dynamically link a registrar function into the compiler process. -fn dylink_registrar( - sess: &Session, - span: Span, - path: PathBuf, - symbol: String, -) -> PluginRegistrarFn { +fn dylink_registrar(sess: &Session, span: Span, path: PathBuf) -> PluginRegistrarFn { use rustc_metadata::dynamic_lib::DynamicLibrary; // Make sure the path contains a / or the linker will search for it. @@ -83,7 +76,7 @@ fn dylink_registrar( }; unsafe { - let registrar = match lib.symbol(&symbol) { + let registrar = match lib.symbol("__rustc_plugin_registrar") { Ok(registrar) => mem::transmute::<*mut u8, PluginRegistrarFn>(registrar), // again fatal if we can't register macros Err(err) => sess.span_fatal(span, &err), @@ -91,7 +84,7 @@ fn dylink_registrar( // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long - // (e.g., an @-box cycle or a thread). + // (e.g., an Rc cycle or a thread). mem::forget(lib); registrar diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d5c759623e3..0b1a99922d6 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -792,12 +792,6 @@ impl Session { ) } - /// Returns the symbol name for the registrar function, - /// given the crate `Svh` and the function `DefIndex`. - pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String { - format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64()) - } - pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String { format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64()) } diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 0c64fe6ea60..1b4e6b4e381 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -55,7 +55,8 @@ pub(super) fn mangle( let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate); - let mut printer = SymbolPrinter { tcx, path: SymbolPath::new(), keep_within_component: false } + let mut printer = SymbolPrinter { tcx, path: SymbolPath::new(), keep_within_component: false }; + printer .print_def_path( def_id, if let ty::InstanceDef::DropGlue(_, _) = instance.def { @@ -198,7 +199,7 @@ struct SymbolPrinter<'tcx> { // `PrettyPrinter` aka pretty printing of e.g. types in paths, // symbol names should have their own printing machinery. -impl Printer<'tcx> for SymbolPrinter<'tcx> { +impl Printer<'tcx> for &mut SymbolPrinter<'tcx> { type Error = fmt::Error; type Path = Self; @@ -242,7 +243,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { Ok(self) } - fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> { + fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> { // only print integers if let ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int { .. })) = ct.val { if ct.ty.is_integral() { @@ -253,7 +254,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { Ok(self) } - fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { + fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { self.write_str(&self.tcx.crate_name(cnum).as_str())?; Ok(self) } @@ -344,7 +345,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { } } -impl PrettyPrinter<'tcx> for SymbolPrinter<'tcx> { +impl PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index ba59ff96f65..850d44eb339 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -164,10 +164,6 @@ fn compute_symbol_name( // FIXME(eddyb) Precompute a custom symbol name based on attributes. let is_foreign = if let Some(def_id) = def_id.as_local() { - if tcx.plugin_registrar_fn(()) == Some(def_id) { - let stable_crate_id = tcx.sess.local_stable_crate_id(); - return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id); - } if tcx.proc_macro_decls_static(()) == Some(def_id) { let stable_crate_id = tcx.sess.local_stable_crate_id(); return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 95c81c5c729..1a195ce18ec 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -2,11 +2,11 @@ use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::free_regions::FreeRegionRelations; +use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; @@ -16,72 +16,6 @@ use rustc_span::Span; use std::ops::ControlFlow; -pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>; - -/// Information about the opaque types whose values we -/// are inferring in this function (these are the `impl Trait` that -/// appear in the return type). -#[derive(Copy, Clone, Debug)] -pub struct OpaqueTypeDecl<'tcx> { - /// The opaque type (`ty::Opaque`) for this declaration. - pub opaque_type: Ty<'tcx>, - - /// The span of this particular definition of the opaque type. So - /// for example: - /// - /// ```ignore (incomplete snippet) - /// type Foo = impl Baz; - /// fn bar() -> Foo { - /// // ^^^ This is the span we are looking for! - /// } - /// ``` - /// - /// In cases where the fn returns `(impl Trait, impl Trait)` or - /// other such combinations, the result is currently - /// over-approximated, but better than nothing. - pub definition_span: Span, - - /// The type variable that represents the value of the opaque type - /// that we require. In other words, after we compile this function, - /// we will be created a constraint like: - /// - /// Foo<'a, T> = ?C - /// - /// where `?C` is the value of this type variable. =) It may - /// naturally refer to the type and lifetime parameters in scope - /// in this function, though ultimately it should only reference - /// those that are arguments to `Foo` in the constraint above. (In - /// other words, `?C` should not include `'b`, even though it's a - /// lifetime parameter on `foo`.) - pub concrete_ty: Ty<'tcx>, - - /// Returns `true` if the `impl Trait` bounds include region bounds. - /// For example, this would be true for: - /// - /// fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b - /// - /// but false for: - /// - /// fn foo<'c>() -> impl Trait<'c> - /// - /// unless `Trait` was declared like: - /// - /// trait Trait<'c>: 'c - /// - /// in which case it would be true. - /// - /// This is used during regionck to decide whether we need to - /// impose any additional constraints to ensure that region - /// variables in `concrete_ty` wind up being constrained to - /// something from `substs` (or, at minimum, things that outlive - /// the fn body). (Ultimately, writeback is responsible for this - /// check.) - pub has_required_region_bounds: bool, - - /// The origin of the opaque type. - pub origin: hir::OpaqueTyOrigin, -} - /// Whether member constraints should be generated for all opaque types #[derive(Debug)] pub enum GenerateMemberConstraints { @@ -98,18 +32,13 @@ pub enum GenerateMemberConstraints { pub trait InferCtxtExt<'tcx> { fn instantiate_opaque_types<T: TypeFoldable<'tcx>>( &self, - parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: T, value_span: Span, - ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>; + ) -> InferOk<'tcx, T>; - fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>( - &self, - opaque_types: &OpaqueTypeMap<'tcx>, - free_region_relations: &FRR, - ); + fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(&self, free_region_relations: &FRR); fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>( &self, @@ -164,28 +93,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `value_span` -- the span where the value came from, used in error reporting fn instantiate_opaque_types<T: TypeFoldable<'tcx>>( &self, - parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: T, value_span: Span, - ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> { + ) -> InferOk<'tcx, T> { debug!( - "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \ + "instantiate_opaque_types(value={:?}, body_id={:?}, \ param_env={:?}, value_span={:?})", - value, parent_def_id, body_id, param_env, value_span, + value, body_id, param_env, value_span, ); - let mut instantiator = Instantiator { - infcx: self, - parent_def_id, - body_id, - param_env, - value_span, - opaque_types: Default::default(), - obligations: vec![], - }; + let mut instantiator = + Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] }; let value = instantiator.instantiate_opaque_types_in_map(value); - InferOk { value: (value, instantiator.opaque_types), obligations: instantiator.obligations } + InferOk { value, obligations: instantiator.obligations } } /// Given the map `opaque_types` containing the opaque @@ -350,12 +271,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `opaque_types` -- the map produced by `instantiate_opaque_types` /// - `free_region_relations` -- something that can be used to relate /// the free regions (`'a`) that appear in the impl trait. - fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>( - &self, - opaque_types: &OpaqueTypeMap<'tcx>, - free_region_relations: &FRR, - ) { - for &(opaque_type_key, opaque_defn) in opaque_types { + fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(&self, free_region_relations: &FRR) { + let opaque_types = self.inner.borrow().opaque_types.clone(); + for (opaque_type_key, opaque_defn) in opaque_types { self.constrain_opaque_type( opaque_type_key, &opaque_defn, @@ -403,19 +321,35 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let span = tcx.def_span(def_id); - // If there are required region bounds, we can use them. - if opaque_defn.has_required_region_bounds { - let bounds = tcx.explicit_item_bounds(def_id); - debug!("{:#?}", bounds); - let bounds: Vec<_> = - bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect(); - debug!("{:#?}", bounds); - let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs); - - let required_region_bounds = - required_region_bounds(tcx, opaque_type, bounds.into_iter()); - debug_assert!(!required_region_bounds.is_empty()); - + // Check if the `impl Trait` bounds include region bounds. + // For example, this would be true for: + // + // fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b + // + // but false for: + // + // fn foo<'c>() -> impl Trait<'c> + // + // unless `Trait` was declared like: + // + // trait Trait<'c>: 'c + // + // in which case it would be true. + // + // This is used during regionck to decide whether we need to + // impose any additional constraints to ensure that region + // variables in `concrete_ty` wind up being constrained to + // something from `substs` (or, at minimum, things that outlive + // the fn body). (Ultimately, writeback is responsible for this + // check.) + let bounds = tcx.explicit_item_bounds(def_id); + debug!("{:#?}", bounds); + let bounds = bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)); + debug!("{:#?}", bounds); + let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs); + + let required_region_bounds = required_region_bounds(tcx, opaque_type, bounds); + if !required_region_bounds.is_empty() { for required_region in required_region_bounds { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), @@ -914,11 +848,9 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { struct Instantiator<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value_span: Span, - opaque_types: OpaqueTypeMap<'tcx>, obligations: Vec<PredicateObligation<'tcx>>, } @@ -968,7 +900,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // ``` if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let parent_def_id = self.parent_def_id; + let parent_def_id = self.infcx.defining_use_anchor; let def_scope_default = || { let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) @@ -980,14 +912,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { impl_trait_fn: Some(parent), origin, .. - }) => (parent == self.parent_def_id.to_def_id(), origin), + }) => (parent == parent_def_id.to_def_id(), origin), // Named `type Foo = impl Bar;` hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, origin, .. }) => ( - may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id), + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin, ), _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), @@ -1028,32 +960,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). - if let Some(opaque_defn) = self.opaque_types.get(&opaque_type_key) { + if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) { debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); return opaque_defn.concrete_ty; } - let span = tcx.def_span(def_id); - debug!("fold_opaque_ty {:?} {:?}", self.value_span, span); - let ty_var = infcx - .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); - - let item_bounds = tcx.explicit_item_bounds(def_id); - debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); - let bounds: Vec<_> = - item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); - - let param_env = tcx.param_env(def_id); - let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( - ObligationCause::misc(span, self.body_id), - param_env, - bounds, - ); - self.obligations.extend(obligations); - - debug!("instantiate_opaque_types: bounds={:?}", bounds); - - let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied()); - debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); + let ty_var = infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: self.value_span, + }); // Make sure that we are in fact defining the *entire* type // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be @@ -1068,23 +982,46 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Foo, impl Bar)`. let definition_span = self.value_span; - self.opaque_types.insert( - OpaqueTypeKey { def_id, substs }, - OpaqueTypeDecl { - opaque_type: ty, - definition_span, - concrete_ty: ty_var, - has_required_region_bounds: !required_region_bounds.is_empty(), - origin, - }, - ); + { + let mut infcx = self.infcx.inner.borrow_mut(); + infcx.opaque_types.insert( + OpaqueTypeKey { def_id, substs }, + OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin }, + ); + infcx.opaque_types_vars.insert(ty_var, ty); + } + debug!("instantiate_opaque_types: ty_var={:?}", ty_var); + self.compute_opaque_type_obligations(opaque_type_key); + + ty_var + } + + fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) { + let infcx = self.infcx; + let tcx = infcx.tcx; + let OpaqueTypeKey { def_id, substs } = opaque_type_key; + + let item_bounds = tcx.explicit_item_bounds(def_id); + debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); + let bounds: Vec<_> = + item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); + + let param_env = tcx.param_env(def_id); + let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( + ObligationCause::misc(self.value_span, self.body_id), + param_env, + bounds, + ); + self.obligations.extend(obligations); + + debug!("instantiate_opaque_types: bounds={:?}", bounds); for predicate in &bounds { if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if projection.ty.references_error() { // No point on adding these obligations since there's a type error involved. - return ty_var; + return; } } } @@ -1096,14 +1033,13 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // This also instantiates nested instances of `impl Trait`. let predicate = self.instantiate_opaque_types_in_map(predicate); - let cause = traits::ObligationCause::new(span, self.body_id, traits::OpaqueType); + let cause = + traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. debug!("instantiate_opaque_types: predicate={:?}", predicate); self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); } - - ty_var } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 3f713ce3c39..ac07cc1f034 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -245,9 +245,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let ObligationCauseCode::WellFormed(Some(wf_loc)) = root_obligation.cause.code.peel_derives() { - if let Some(cause) = - self.tcx.diagnostic_hir_wf_check((obligation.predicate, wf_loc.clone())) - { + if let Some(cause) = self.tcx.diagnostic_hir_wf_check(( + tcx.erase_regions(obligation.predicate), + wf_loc.clone(), + )) { obligation.cause = cause; span = obligation.cause.span; } diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index dee81510b79..10c3a97e73a 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -593,13 +593,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { orig_expected: Expectation<'tcx>, ) -> Option<Span> { match (orig_expected, self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty))) { - (Expectation::ExpectHasType(expected), Some((id, ty))) + (Expectation::ExpectHasType(expected), Some((_id, ty))) if self.in_tail_expr && self.can_coerce(outer_ty, expected) => { let impl_trait_ret_ty = - self.infcx.instantiate_opaque_types(id, self.body_id, self.param_env, ty, span); - let mut suggest_box = !impl_trait_ret_ty.obligations.is_empty(); - for o in impl_trait_ret_ty.obligations { + self.infcx.instantiate_opaque_types(self.body_id, self.param_env, ty, span); + assert!( + impl_trait_ret_ty.obligations.is_empty(), + "we should never get new obligations here" + ); + let obligations = self.fulfillment_cx.borrow().pending_obligations(); + let mut suggest_box = !obligations.is_empty(); + for o in obligations { match o.predicate.kind().skip_binder() { ty::PredicateKind::Trait(t, constness) => { let pred = ty::PredicateKind::Trait( diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ba99e0c03d8..8b5b7e3e52c 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -94,69 +94,8 @@ pub(super) fn check_fn<'a, 'tcx>( let declared_ret_ty = fn_sig.output(); - let feature = match tcx.hir().get(fn_id) { - // TAIT usage in function return position. - // Example: - // - // ```rust - // type Foo = impl Debug; - // fn bar() -> Foo { 42 } - // ``` - Node::Item(hir::Item { kind: ItemKind::Fn(..), .. }) | - // TAIT usage in associated function return position. - // - // Example with a free type alias: - // - // ```rust - // type Foo = impl Debug; - // impl SomeTrait for SomeType { - // fn bar() -> Foo { 42 } - // } - // ``` - // - // Example with an associated TAIT: - // - // ```rust - // impl SomeTrait for SomeType { - // type Foo = impl Debug; - // fn bar() -> Self::Foo { 42 } - // } - // ``` - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(..), .. - }) => None, - // Forbid TAIT in trait declarations for now. - // Examples: - // - // ```rust - // type Foo = impl Debug; - // trait Bar { - // fn bar() -> Foo; - // } - // trait Bop { - // type Bop: PartialEq<Foo>; - // } - // ``` - Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(..), - .. - }) | - // Forbid TAIT in closure return position for now. - // Example: - // - // ```rust - // type Foo = impl Debug; - // let x = |y| -> Foo { 42 + y }; - // ``` - Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => Some(sym::type_alias_impl_trait), - node => bug!("Item being checked wasn't a function/closure: {:?}", node), - }; - let revealed_ret_ty = fcx.instantiate_opaque_types_from_value( - fn_id, - declared_ret_ty, - decl.output.span(), - feature, - ); + let revealed_ret_ty = + fcx.instantiate_opaque_types_from_value(declared_ret_ty, decl.output.span()); debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); fcx.ret_type_span = Some(decl.output.span()); @@ -711,10 +650,11 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = traits::ObligationCause::misc(span, hir_id); - let (_, opaque_type_map) = inh.register_infer_ok_obligations( - infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span), + let _ = inh.register_infer_ok_obligations( + infcx.instantiate_opaque_types(hir_id, param_env, opaque_ty, span), ); + let opaque_type_map = infcx.inner.borrow().opaque_types.clone(); for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map { match infcx .at(&misc_cause, param_env) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 831b573e156..a5362856511 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1313,15 +1313,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } } else if check_completeness && !error_happened && !remaining_fields.is_empty() { - let no_accessible_remaining_fields = remaining_fields - .iter() - .find(|(_, (_, field))| { - field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) - }) - .is_none(); + let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| { + !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) + }); - if no_accessible_remaining_fields { - self.report_no_accessible_fields(adt_ty, span); + if inaccessible_remaining_fields { + self.report_inaccessible_fields(adt_ty, span); } else { self.report_missing_fields(adt_ty, span, remaining_fields); } @@ -1398,7 +1395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } - /// Report an error for a struct field expression when there are no visible fields. + /// Report an error for a struct field expression when there are invisible fields. /// /// ```text /// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields @@ -1409,7 +1406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// error: aborting due to previous error /// ``` - fn report_no_accessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) { + fn report_inaccessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) { self.tcx.sess.span_err( span, &format!( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index f5776ae7cf6..b84a79b768c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -29,12 +29,11 @@ use rustc_middle::ty::{ }; use rustc_session::lint; use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; -use rustc_session::parse::feature_err; use rustc_span::edition::Edition; +use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{self, BytePos, MultiSpan, Span}; -use rustc_span::{hygiene::DesugaringKind, Symbol}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::opaque_types::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; @@ -363,50 +362,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Replaces the opaque types from the given value with type variables, /// and records the `OpaqueTypeMap` for later use during writeback. See /// `InferCtxt::instantiate_opaque_types` for more details. + #[instrument(skip(self, value_span), level = "debug")] pub(in super::super) fn instantiate_opaque_types_from_value<T: TypeFoldable<'tcx>>( &self, - parent_id: hir::HirId, value: T, value_span: Span, - feature: Option<Symbol>, ) -> T { - let parent_def_id = self.tcx.hir().local_def_id(parent_id); - debug!( - "instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})", - parent_def_id, value - ); - - let (value, opaque_type_map) = - self.register_infer_ok_obligations(self.instantiate_opaque_types( - parent_def_id, - self.body_id, - self.param_env, - value, - value_span, - )); - - let mut opaque_types = self.opaque_types.borrow_mut(); - let mut opaque_types_vars = self.opaque_types_vars.borrow_mut(); - - for (ty, decl) in opaque_type_map { - if let Some(feature) = feature { - if let hir::OpaqueTyOrigin::TyAlias = decl.origin { - if !self.tcx.features().enabled(feature) { - feature_err( - &self.tcx.sess.parse_sess, - feature, - value_span, - "type alias impl trait is not permitted here", - ) - .emit(); - } - } - } - let _ = opaque_types.insert(ty, decl); - let _ = opaque_types_vars.insert(decl.concrete_ty, decl.opaque_type); - } - - value + self.register_infer_ok_obligations(self.instantiate_opaque_types( + self.body_id, + self.param_env, + value, + value_span, + )) } /// Convenience method which tracks extra diagnostic information for normalization @@ -726,7 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We treat this as a non-defining use by making the inference // variable fall back to the opaque type itself. if let FallbackMode::All = mode { - if let Some(opaque_ty) = self.opaque_types_vars.borrow().get(ty) { + if let Some(opaque_ty) = self.infcx.inner.borrow().opaque_types_vars.get(ty) { debug!( "fallback_if_possible: falling back opaque type var {:?} to {:?}", ty, opaque_ty diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 7e43e36fe55..fb7beae70ba 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -1,18 +1,15 @@ use super::callee::DeferredCallResolution; use super::MaybeInProgressTables; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; use rustc_hir::def_id::{DefIdMap, LocalDefId}; use rustc_hir::HirIdMap; use rustc_infer::infer; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{self, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::opaque_types::OpaqueTypeDecl; use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt}; use std::cell::RefCell; @@ -55,19 +52,6 @@ pub struct Inherited<'a, 'tcx> { pub(super) deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>, - // Opaque types found in explicit return types and their - // associated fresh inference variable. Writeback resolves these - // variables to get the concrete type, which can be used to - // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions. - pub(super) opaque_types: RefCell<VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>>, - - /// A map from inference variables created from opaque - /// type instantiations (`ty::Infer`) to the actual opaque - /// type (`ty::Opaque`). Used during fallback to map unconstrained - /// opaque type inference variables to their corresponding - /// opaque type. - pub(super) opaque_types_vars: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>, - pub(super) body_id: Option<hir::BodyId>, } @@ -124,8 +108,6 @@ impl Inherited<'a, 'tcx> { deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), - opaque_types: RefCell::new(Default::default()), - opaque_types_vars: RefCell::new(Default::default()), body_id, } } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 77586ce4852..c7a7462668a 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1695,8 +1695,8 @@ fn print_disambiguation_help( source_map: &source_map::SourceMap, ) { let mut applicability = Applicability::MachineApplicable; - let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) { - format!( + let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) { + let args = format!( "({}{})", if rcvr_ty.is_region_ptr() { if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" } @@ -1710,12 +1710,12 @@ fn print_disambiguation_help( })) .collect::<Vec<_>>() .join(", "), - ) + ); + (span, format!("{}::{}{}", trait_name, item_name, args)) } else { - String::new() + (span.with_hi(item_name.span.lo()), format!("{}::", trait_name)) }; - let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args); - err.span_suggestion( + err.span_suggestion_verbose( span, &format!( "disambiguate the {} for {}", diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index db77d155a2b..dae574bb7bf 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1250,15 +1250,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit(); } } else if !etc && !unmentioned_fields.is_empty() { - let no_accessible_unmentioned_fields = !unmentioned_fields.iter().any(|(field, _)| { - field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx) - }); + let accessible_unmentioned_fields: Vec<_> = unmentioned_fields + .iter() + .copied() + .filter(|(field, _)| { + field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx) + }) + .collect(); - if no_accessible_unmentioned_fields { + if accessible_unmentioned_fields.is_empty() { unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields)); } else { - unmentioned_err = - Some(self.error_unmentioned_fields(pat, &unmentioned_fields, &fields)); + unmentioned_err = Some(self.error_unmentioned_fields( + pat, + &accessible_unmentioned_fields, + accessible_unmentioned_fields.len() != unmentioned_fields.len(), + &fields, + )); } } match (inexistent_fields_err, unmentioned_err) { @@ -1583,17 +1591,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &Pat<'_>, unmentioned_fields: &[(&ty::FieldDef, Ident)], + have_inaccessible_fields: bool, fields: &'tcx [hir::PatField<'tcx>], ) -> DiagnosticBuilder<'tcx> { + let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" }; let field_names = if unmentioned_fields.len() == 1 { - format!("field `{}`", unmentioned_fields[0].1) + format!("field `{}`{}", unmentioned_fields[0].1, inaccessible) } else { let fields = unmentioned_fields .iter() .map(|(_, name)| format!("`{}`", name)) .collect::<Vec<String>>() .join(", "); - format!("fields {}", fields) + format!("fields {}{}", fields, inaccessible) }; let mut err = struct_span_err!( self.tcx.sess, @@ -1624,17 +1634,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( sp, &format!( - "include the missing field{} in the pattern", + "include the missing field{} in the pattern{}", if len == 1 { "" } else { "s" }, + if have_inaccessible_fields { " and ignore the inaccessible fields" } else { "" } ), format!( - "{}{}{}", + "{}{}{}{}", prefix, unmentioned_fields .iter() .map(|(_, name)| name.to_string()) .collect::<Vec<_>>() .join(", "), + if have_inaccessible_fields { ", .." } else { "" }, postfix, ), Applicability::MachineApplicable, diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 8f8514cadb7..ca6828cfdf6 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -291,10 +291,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.visit_body(body); self.visit_region_obligations(body_id.hir_id); - self.constrain_opaque_types( - &self.fcx.opaque_types.borrow(), - self.outlives_environment.free_region_map(), - ); + self.constrain_opaque_types(self.outlives_environment.free_region_map()); } fn visit_region_obligations(&mut self, hir_id: hir::HirId) { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index e6eac16667d..959ab69a679 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -498,7 +498,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_opaque_types(&mut self, span: Span) { - for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() { + let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone(); + for (opaque_type_key, opaque_defn) in opaque_types { let hir_id = self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local()); let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 96b3fa9aa01..b9483d6f987 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -190,8 +190,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // Try to use the segment resolution if it is valid, otherwise we // default to the path resolution. let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); + use def::CtorOf; let generics = match res { - Res::Def(DefKind::Ctor(..), def_id) => { + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx.generics_of( + tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap(), + ), + Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { tcx.generics_of(tcx.parent(def_id).unwrap()) } // Other `DefKind`s don't have generics and would ICE when calling @@ -200,7 +204,6 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy | DefKind::TyAlias |
