diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8a3f76415968e..6d6438920c09b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -754,7 +754,7 @@ fn validate_generic_param_order( GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().const_generics; + let unordered = sess.features_untracked().unordered_const_ty_params(); (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) } }; diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0679ccabe726c..077ab06d82dde 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -586,12 +586,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { let is_fn = match i.kind { - ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => { - if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { - gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); - } - true - } + ast::AssocItemKind::Fn(_) => true, ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( diff --git a/compiler/rustc_error_codes/src/error_codes/E0379.md b/compiler/rustc_error_codes/src/error_codes/E0379.md index 930204847ecd8..ab438e4144712 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0379.md +++ b/compiler/rustc_error_codes/src/error_codes/E0379.md @@ -3,8 +3,6 @@ A trait method was declared const. Erroneous code example: ```compile_fail,E0379 -#![feature(const_fn)] - trait Foo { const fn bar() -> u32; // error! } diff --git a/compiler/rustc_error_codes/src/error_codes/E0764.md b/compiler/rustc_error_codes/src/error_codes/E0764.md index 0a2e2290e77c2..152627cf6545f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0764.md +++ b/compiler/rustc_error_codes/src/error_codes/E0764.md @@ -3,7 +3,6 @@ A mutable reference was used in a constant. Erroneous code example: ```compile_fail,E0764 -#![feature(const_fn)] #![feature(const_mut_refs)] fn main() { @@ -27,7 +26,6 @@ Remember: you cannot use a function call inside a constant or static. However, you can totally use it in constant functions: ``` -#![feature(const_fn)] #![feature(const_mut_refs)] const fn foo(x: usize) -> usize { diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index ec122e7be6e8e..e262d95bb70f2 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -1,39 +1,52 @@ // Code for creating styled buffers use crate::snippet::{Style, StyledString}; -use std::iter; #[derive(Debug)] pub struct StyledBuffer { - text: Vec>, - styles: Vec>, + lines: Vec>, +} + +#[derive(Debug, Clone)] +struct StyledChar { + chr: char, + style: Style, +} + +impl StyledChar { + const SPACE: Self = StyledChar::new(' ', Style::NoStyle); + + const fn new(chr: char, style: Style) -> Self { + StyledChar { chr, style } + } } impl StyledBuffer { pub fn new() -> StyledBuffer { - StyledBuffer { text: vec![], styles: vec![] } + StyledBuffer { lines: vec![] } } + /// Returns content of `StyledBuffer` splitted by lines and line styles pub fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. - debug_assert!(self.text.iter().all(|r| !r.contains(&'\t'))); + debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - for (row, row_style) in iter::zip(&self.text, &self.styles) { + for styled_line in &self.lines { let mut current_style = Style::NoStyle; let mut current_text = String::new(); - for (&c, &s) in iter::zip(row, row_style) { - if s != current_style { + for sc in styled_line { + if sc.style != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); } - current_style = s; + current_style = sc.style; current_text = String::new(); } - current_text.push(c); + current_text.push(sc.chr); } if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); @@ -49,29 +62,25 @@ impl StyledBuffer { } fn ensure_lines(&mut self, line: usize) { - while line >= self.text.len() { - self.text.push(vec![]); - self.styles.push(vec![]); + if line >= self.lines.len() { + self.lines.resize(line + 1, Vec::new()); } } + /// Sets `chr` with `style` for given `line`, `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); - if col < self.text[line].len() { - self.text[line][col] = chr; - self.styles[line][col] = style; - } else { - let mut i = self.text[line].len(); - while i < col { - self.text[line].push(' '); - self.styles[line].push(Style::NoStyle); - i += 1; - } - self.text[line].push(chr); - self.styles[line].push(style); + if col >= self.lines[line].len() { + self.lines[line].resize(col + 1, StyledChar::SPACE); } + self.lines[line][col] = StyledChar::new(chr, style); } + /// Sets `string` with `style` for given `line`, starting from `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { @@ -80,32 +89,40 @@ impl StyledBuffer { } } + /// For given `line` inserts `string` with `style` before old content of that line, + /// adding lines if needed pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.chars().count(); - // Push the old content over to make room for new content - for _ in 0..string_len { - self.styles[line].insert(0, Style::NoStyle); - self.text[line].insert(0, ' '); + if !self.lines[line].is_empty() { + // Push the old content over to make room for new content + for _ in 0..string_len { + self.lines[line].insert(0, StyledChar::SPACE); + } } self.puts(line, 0, string, style); } + /// For given `line` inserts `string` with `style` after old content of that line, + /// adding lines if needed pub fn append(&mut self, line: usize, string: &str, style: Style) { - if line >= self.text.len() { + if line >= self.lines.len() { self.puts(line, 0, string, style); } else { - let col = self.text[line].len(); + let col = self.lines[line].len(); self.puts(line, col, string, style); } } pub fn num_lines(&self) -> usize { - self.text.len() + self.lines.len() } + /// Set `style` for `line`, `col_start..col_end` range if: + /// 1. That line and column range exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style_range( &mut self, line: usize, @@ -119,10 +136,13 @@ impl StyledBuffer { } } + /// Set `style` for `line`, `col` if: + /// 1. That line and column exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { - if let Some(ref mut line) = self.styles.get_mut(line) { - if let Some(s) = line.get_mut(col) { - if *s == Style::NoStyle || *s == Style::Quotation || overwrite { + if let Some(ref mut line) = self.lines.get_mut(line) { + if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { + if overwrite || *s == Style::NoStyle || *s == Style::Quotation { *s = style; } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 72babb7aec171..7ae7e0094c6d1 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -63,6 +63,10 @@ macro_rules! declare_features { _ => panic!("`{}` was not listed in `declare_features`", feature), } } + + pub fn unordered_const_ty_params(&self) -> bool { + self.const_generics || self.const_generics_defaults + } } }; } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 685429863faff..5baaaad7370fc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -296,7 +296,9 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics }, + GenericArg::Const(_) => { + ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } + } } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 5820e7a261230..77d083fc5e967 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1095,8 +1095,8 @@ impl<'a> State<'a> { fn print_else(&mut self, els: Option<&hir::Expr<'_>>) { match els { - Some(_else) => { - match _else.kind { + Some(else_) => { + match else_.kind { // "another else-if" hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); @@ -1114,6 +1114,26 @@ impl<'a> State<'a> { self.s.word(" else "); self.print_block(&b) } + hir::ExprKind::Match(ref expr, arms, _) => { + // else if let desugared to match + assert!(arms.len() == 2, "if let desugars to match with two arms"); + + self.s.word(" else "); + self.s.word("{"); + + self.cbox(INDENT_UNIT); + self.ibox(INDENT_UNIT); + self.word_nbsp("match"); + self.print_expr_as_cond(&expr); + self.s.space(); + self.bopen(); + for arm in arms { + self.print_arm(arm); + } + self.bclose(expr.span); + + self.s.word("}"); + } // BLEAH, constraints would be great here _ => { panic!("print_if saw if with weird alternative"); diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index d30a8693959f3..c8fdbc30d1591 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -36,7 +36,7 @@ impl GenericParamDefKind { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, GenericParamDefKind::Const { .. } => { - ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } } } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 87e28f7fcc592..c5f12c0c691b3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -472,17 +472,6 @@ impl<'a> Resolver<'a> { ); err } - ResolutionError::ParamInAnonConstInTyDefault(name) => { - let mut err = self.session.struct_span_err( - span, - "constant values inside of type parameter defaults must not depend on generic parameters", - ); - err.span_label( - span, - format!("the anonymous constant must not depend on the parameter `{}`", name), - ); - err - } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9321f11f65933..92f21191de430 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind); - let mut found_default = false; - default_ban_rib.bindings.extend(generics.params.iter().filter_map( - |param| match param.kind { - GenericParamKind::Type { default: Some(_), .. } - | GenericParamKind::Const { default: Some(_), .. } => { - found_default = true; - Some((Ident::with_dummy_span(param.ident.name), Res::Err)) + let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + for param in generics.params.iter() { + match param.kind { + GenericParamKind::Type { .. } => { + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } - _ => None, - }, - )); + GenericParamKind::Const { .. } => { + forward_const_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + } + GenericParamKind::Lifetime => {} + } + } // rust-lang/rust#61631: The type `Self` is essentially // another type parameter. For ADTs, we consider it @@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } if let Some(ref ty) = default { - self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| { - // HACK: We use an empty `ForwardGenericParamBanRibKind` here which - // is only used to forbid the use of const parameters inside of - // type defaults. - // - // While the rib name doesn't really fit here, it does allow us to use the same - // code for both const and type parameters. - this.visit_ty(ty); - }); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_ty(ty); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); + forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { - // FIXME(const_generics_defaults): handle `default` value here - for bound in ¶m.bounds { - self.visit_param_bound(bound); - } + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + // Const parameters can't have param bounds. + assert!(param.bounds.is_empty()); + self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + + if let Some(ref expr) = default { + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_anon_const(expr); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this const parameter. + forward_const_ban_rib + .bindings + .remove(&Ident::with_dummy_span(param.ident.name)); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 129954381c9ba..1d1969f7e78ab 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -239,8 +239,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), - /// constant values inside of type parameter defaults must not depend on generic parameters. - ParamInAnonConstInTyDefault(Symbol), /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. @@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> { } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { - let mut in_ty_param_default = false; for rib in ribs { - let has_generic_params = match rib.kind { + let has_generic_params: HasGenericParams = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => { + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; } - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> { } } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } // This was an attempt to use a type parameter outside its scope. @@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> { ribs.next(); } - let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => continue, - - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => continue, + ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> { return Res::Err; } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } ItemRibKind(has_generic_params) => has_generic_params, diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 7a297f2c65f13..2bbb38c294d57 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -286,7 +286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ParamKindOrd::Const { unordered: tcx .features() - .const_generics, + .unordered_const_ty_params(), } } }, @@ -309,7 +309,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx.features().const_generics, + unordered: tcx + .features() + .unordered_const_ty_params(), }, }), Some(&format!( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index b6de491911ab7..62a1584d16be0 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -513,7 +513,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); if !infer_args && has_default { - tcx.const_param_default(param.def_id).into() + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { if infer_args { self.astconv.ct_infer(ty, Some(param), self.span).into() diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 427f967a9b6bd..236fec94bdba7 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1494,7 +1494,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some((expr, _)), Some((fn_decl, _, _))) = (expression, fcx.get_node_fn_decl(parent_item)) { - fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found, parent_id); + fcx.suggest_missing_break_or_return_expr( + &mut err, expr, fn_decl, expected, found, id, parent_id, + ); } if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 9ace455042103..a50f8e1c65599 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default, .. } => { if !infer_args && has_default { - tcx.const_param_default(param.def_id).into() + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { self.fcx.var_for_def(self.span, param) } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index b758334484535..d6b1e56316b37 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, ItemKind, Node}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node, Stmt, StmtKind}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; @@ -55,7 +55,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pointing_at_return_type = self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); - self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found, fn_id); + self.suggest_missing_break_or_return_expr( + err, expr, &fn_decl, expected, found, blk_id, fn_id, + ); } pointing_at_return_type } @@ -472,7 +474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(in super::super) fn suggest_missing_return_expr( + pub(in super::super) fn suggest_missing_break_or_return_expr( &self, err: &mut DiagnosticBuilder<'_>, expr: &'tcx hir::Expr<'tcx>, @@ -480,14 +482,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, id: hir::HirId, + fn_id: hir::HirId, ) { if !expected.is_unit() { return; } let found = self.resolve_vars_with_obligations(found); + + let in_loop = self.is_loop(id) + || self.tcx.hir().parent_iter(id).any(|(parent_id, _)| self.is_loop(parent_id)); + + let in_local_statement = self.is_local_statement(id) + || self + .tcx + .hir() + .parent_iter(id) + .any(|(parent_id, _)| self.is_local_statement(parent_id)); + + if in_loop && in_local_statement { + err.multipart_suggestion( + "you might have meant to break the loop with this value", + vec![ + (expr.span.shrink_to_lo(), "break ".to_string()), + (expr.span.shrink_to_hi(), ";".to_string()), + ], + Applicability::MaybeIncorrect, + ); + return; + } + if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(self, ty); - let bound_vars = self.tcx.late_bound_vars(id); + let bound_vars = self.tcx.late_bound_vars(fn_id); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.normalize_associated_types_in(expr.span, ty); if self.can_coerce(found, ty) { @@ -514,4 +540,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None); } } + + fn is_loop(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. })) + } + + fn is_local_statement(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + } } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 02fe8312c4c1f..73e35f0171aa7 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -988,6 +988,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut alt_rcvr_sugg = false; if let SelfSource::MethodCall(rcvr) = source { debug!(?span, ?item_name, ?rcvr_ty, ?rcvr); + let skippable = [ + self.tcx.lang_items().clone_trait(), + self.tcx.lang_items().deref_trait(), + self.tcx.lang_items().deref_mut_trait(), + self.tcx.lang_items().drop_trait(), + ]; // Try alternative arbitrary self types that could fulfill this call. // FIXME: probe for all types that *could* be arbitrary self-types, not // just this list. @@ -996,6 +1002,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "), (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"), ] { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + rcvr_ty, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + // If the method is defined for the receiver we have, it likely wasn't `use`d. + // We point at the method, but we just skip the rest of the check for arbitrary + // self types and rely on the suggestion to `use` the trait from + // `suggest_valid_traits`. + let did = Some(pick.item.container.id()); + let skip = skippable.contains(&did); + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", rcvr_ty), + ); + } + break; + } for (rcvr_ty, pre) in &[ (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"), (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"), @@ -1015,13 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We don't want to suggest a container type when the missing // method is `.clone()` or `.deref()` otherwise we'd suggest // `Arc::new(foo).clone()`, which is far from what the user wants. - let skip = [ - self.tcx.lang_items().clone_trait(), - self.tcx.lang_items().deref_trait(), - self.tcx.lang_items().deref_mut_trait(), - self.tcx.lang_items().drop_trait(), - ] - .contains(&did); + let skip = skippable.contains(&did); // Make sure the method is defined for the *actual* receiver: we don't // want to treat `Box` as a receiver if it only works because of // an autoderef to `&self` @@ -1047,7 +1068,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) { + if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 887cc42a1dd27..26871d6f0285c 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -728,20 +728,36 @@ fn check_where_clauses<'tcx, 'fcx>( // // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. for param in &generics.params { - if let GenericParamDefKind::Type { .. } = param.kind { - if is_our_default(¶m) { - let ty = fcx.tcx.type_of(param.def_id); - // Ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ``). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + match param.kind { + GenericParamDefKind::Type { .. } => { + if is_our_default(¶m) { + let ty = fcx.tcx.type_of(param.def_id); + // Ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ``). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation( + ty.into(), + fcx.tcx.def_span(param.def_id), + ObligationCauseCode::MiscObligation, + ); + } + } + } + GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): Figure out if this + // is the behavior we want, see the comment further below. + if is_our_default(¶m) { + let default_ct = tcx.const_param_default(param.def_id); fcx.register_wf_obligation( - ty.into(), + default_ct.into(), fcx.tcx.def_span(param.def_id), ObligationCauseCode::MiscObligation, ); } } + // Doesn't have defaults. + GenericParamDefKind::Lifetime => {} } } @@ -774,14 +790,25 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): I(@lcnr) feel like always + // using the const parameter is the right choice here, even + // if it needs substs. + // + // Before stabilizing this we probably want to get some tests + // where this makes a difference and figure out what's the exact + // behavior we want here. + + // If the param has a default, ... if is_our_default(param) { let default_ct = tcx.const_param_default(param.def_id); - // Const params currently have to be concrete. - assert!(!default_ct.needs_subst()); - default_ct.into() - } else { - fcx.tcx.mk_param_from_def(param) + // ... and it's not a dependent default, ... + if !default_ct.needs_subst() { + // ... then substitute it with the default. + return default_ct.into(); + } } + + fcx.tcx.mk_param_from_def(param) } } }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 3692642b6e20d..46ee82454326a 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1327,13 +1327,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option Visitor<'v> for AnonConstInParamListDetector { +impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1341,15 +1341,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector { } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - let prev = self.in_param_list; - self.in_param_list = true; - intravisit::walk_generic_param(self, p); - self.in_param_list = prev; + if let GenericParamKind::Const { ref ty, default: _ } = p.kind { + let prev = self.in_param_ty; + self.in_param_ty = true; + self.visit_ty(ty); + self.in_param_ty = prev; + } } fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { - if self.in_param_list && self.ct == c.hir_id { - self.found_anon_const_in_list = true; + if self.in_param_ty && self.ct == c.hir_id { + self.found_anon_const_in_param_ty = true; } else { intravisit::walk_anon_const(self, c) } @@ -1377,27 +1379,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let mut in_param_list = false; + let mut in_param_ty = false; for (_parent, node) in tcx.hir().parent_iter(hir_id) { if let Some(generics) = node.generics() { - let mut visitor = AnonConstInParamListDetector { - in_param_list: false, - found_anon_const_in_list: false, + let mut visitor = AnonConstInParamTyDetector { + in_param_ty: false, + found_anon_const_in_param_ty: false, ct: hir_id, }; visitor.visit_generics(generics); - in_param_list = visitor.found_anon_const_in_list; + in_param_ty = visitor.found_anon_const_in_param_ty; break; } } - if in_param_list { + if in_param_ty { // We do not allow generic parameters in anon consts if we are inside - // of a param list. - // - // This affects both default type bindings, e.g. `struct()]>(T, U)`, - // and the types of const parameters, e.g. `struct V();`. + // of a const parameter type, e.g. `struct Foo` is not allowed. None } else if tcx.lazy_normalization() { // HACK(eddyb) this provides the correct generics when diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs index 769b6e952dc9c..6514409698e3e 100644 --- a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs +++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -1,4 +1,4 @@ -#![feature(const_generics)] +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr new file mode 100644 index 0000000000000..e0e2b6c69f280 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr @@ -0,0 +1,18 @@ +error: constant expression depends on a generic parameter + --> $DIR/complex-generic-default-expr.rs:6:34 + | +LL | struct Foo; + | ^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/complex-generic-default-expr.rs:10:21 + | +LL | struct Bar() }>(T); + | ^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr new file mode 100644 index 0000000000000..58abd8db9f09f --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:6:47 + | +LL | struct Foo; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:10:62 + | +LL | struct Bar() }>(T); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 0000000000000..a7b712f7b4b86 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,14 @@ +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters may not be used in const operations + +struct Bar() }>(T); +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs index 150c70770ae51..4fa21b8b1fb78 100644 --- a/src/test/ui/const-generics/defaults/const-default.rs +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -1,6 +1,6 @@ // run-pass - -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs new file mode 100644 index 0000000000000..59ac261f44fd5 --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs @@ -0,0 +1,23 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo([u8; N], [u8; M]); + +fn foo() -> Foo { + let x = [0; N]; + Foo(x, x) +} + +// To check that we actually apply the correct substs for const param defaults. +fn concrete_foo() -> Foo<13> { + Foo(Default::default(), Default::default()) +} + + +fn main() { + let val = foo::<13>(); + assert_eq!(val.0, val.1); + + let val = concrete_foo(); + assert_eq!(val.0, val.1); +} diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs new file mode 100644 index 0000000000000..3f534ca0308ba --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo([0; N]) + } +} + +fn main() { + assert_eq!(Foo::new().0, [0; 10]); +} diff --git a/src/test/ui/const-generics/defaults/default-on-impl.full.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr new file mode 100644 index 0000000000000..c417a26842ed1 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:8:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr new file mode 100644 index 0000000000000..c417a26842ed1 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:8:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 0000000000000..735549defeaf0 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs new file mode 100644 index 0000000000000..4bb56c6a1c08c --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -0,0 +1,5 @@ +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo; +//~^ ERROR evaluation of constant value failed +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr new file mode 100644 index 0000000000000..8464ea98bf695 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:3:28 + | +LL | struct Foo; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs index b39e69ab10b66..32acf567cf2b9 100644 --- a/src/test/ui/const-generics/defaults/external.rs +++ b/src/test/ui/const-generics/defaults/external.rs @@ -1,5 +1,7 @@ // aux-build:const_defaulty.rs // check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr index c4a666a829d8c..29d835e36c6eb 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr @@ -1,5 +1,5 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo(&'a (), T); | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr index 69a490978d1df..985e7b655ece9 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr @@ -1,26 +1,14 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo(&'a (), T); - | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:32 - | -LL | struct Foo(&'a (), T); - | ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: lifetime parameters must be declared prior to const parameters +error: lifetime parameters must be declared prior to type parameters --> $DIR/intermixed-lifetime.rs:10:37 | LL | struct Bar(&'a (), T); - | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:10:28 - | -LL | struct Bar(&'a (), T); - | -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index 9e83bf92a59b9..307e3aaf1fbf3 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -1,15 +1,13 @@ -// revisions: full min // Checks that lifetimes cannot be interspersed between consts and types. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct Foo(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters -//[min]~^^ Error type parameters must be declared prior to const parameters struct Bar(&'a (), T); -//[full]~^ Error lifetime parameters must be declared prior to type parameters -//[min]~^^ Error type parameters must be declared prior to const parameters -//[min]~| Error lifetime parameters must be declared prior to const parameters +//~^ Error lifetime parameters must be declared prior to type parameters fn main() {} diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr similarity index 90% rename from src/test/ui/const-generics/defaults/mismatch.stderr rename to src/test/ui/const-generics/defaults/mismatch.full.stderr index ff72c71c40f0f..be4f364d8ee62 100644 --- a/src/test/ui/const-generics/defaults/mismatch.stderr +++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/mismatch.rs:11:28 + --> $DIR/mismatch.rs:12:28 | LL | let e: Example::<13> = (); | ------------- ^^ expected struct `Example`, found `()` @@ -7,7 +7,7 @@ LL | let e: Example::<13> = (); | expected due to this error[E0308]: mismatched types - --> $DIR/mismatch.rs:13:34 + --> $DIR/mismatch.rs:14:34 | LL | let e: Example2:: = (); | ------------------- ^^ expected struct `Example2`, found `()` @@ -18,7 +18,7 @@ LL | let e: Example2:: = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:15:34 + --> $DIR/mismatch.rs:16:34 | LL | let e: Example3::<13, u32> = (); | ------------------- ^^ expected struct `Example3`, found `()` @@ -29,7 +29,7 @@ LL | let e: Example3::<13, u32> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:17:28 + --> $DIR/mismatch.rs:18:28 | LL | let e: Example3::<7> = (); | ------------- ^^ expected struct `Example3`, found `()` @@ -40,7 +40,7 @@ LL | let e: Example3::<7> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:21:28 + --> $DIR/mismatch.rs:22:28 | LL | let e: Example4::<7> = (); | ------------- ^^ expected struct `Example4`, found `()` diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr new file mode 100644 index 0000000000000..be4f364d8ee62 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:12:28 + | +LL | let e: Example::<13> = (); + | ------------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:14:34 + | +LL | let e: Example2:: = (); + | ------------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:34 + | +LL | let e: Example3::<13, u32> = (); + | ------------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:18:28 + | +LL | let e: Example3::<7> = (); + | ------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7_usize>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:22:28 + | +LL | let e: Example4::<7> = (); + | ------------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs index d85b756f538dc..68a640c0a08b3 100644 --- a/src/test/ui/const-generics/defaults/mismatch.rs +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -1,4 +1,5 @@ -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs index a25d4baca1a97..7a57950dfc924 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -10,4 +10,4 @@ trait Foo {} fn foo() {} -struct Range; +struct Range; diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout index f7a1d2ca4b2ef..f549993c413d4 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -17,4 +17,4 @@ trait Foo { } fn foo() { } struct Range; + FROM>; diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs index 18ecf46729977..c64c2974c8f8f 100644 --- a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs +++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -6,7 +6,7 @@ #![allow(incomplete_features)] #[repr(C)] -pub struct Loaf { +pub struct Loaf { head: [T; N], slice: [T], } diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr deleted file mode 100644 index 0746c64ac8cf4..0000000000000 --- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameters must be declared prior to const parameters - --> $DIR/simple-defaults.rs:8:40 - | -LL | struct FixedOutput<'a, const N: usize, T=u32> { - | ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs index cb66c7769bb23..c003cb2c5a6ee 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.rs +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -1,12 +1,12 @@ -// [full] run-pass -// revisions: min full -// Checks some basic test cases for defaults. +// run-pass +// Checks that type param defaults are allowed after const params. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] #![allow(dead_code)] struct FixedOutput<'a, const N: usize, T=u32> { - //[min]~^ ERROR type parameters must be declared prior to const parameters out: &'a [T; N], } diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 0000000000000..e68075ee3c627 --- /dev/null +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,19 @@ +// check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +struct N; + +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index accc73134d899..eb0bcb2821556 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -1,19 +1,8 @@ error: generic parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 + --> $DIR/wrong-order.rs:6:10 | LL | struct A { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted - -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wrong-order.rs:2:27 - | -LL | #![cfg_attr(full, feature(const_generics))] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index c8f1d471b244b..eb0bcb2821556 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -1,10 +1,8 @@ error: generic parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 + --> $DIR/wrong-order.rs:6:10 | LL | struct A { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 5c2d9b8ad4751..88e9e96ba43f9 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -1,5 +1,7 @@ // revisions: full min -#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct A { //~^ ERROR generic parameters with a default must be trailing diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index c2b7b206653a6..e8fd9e7769b79 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,22 +1,17 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar(T); | ^ | = note: using type defaults and const parameters in the same parameter list is currently not permitted -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 - | -LL | struct Foo()]>(T, U); - | ^ the anonymous constant must not depend on the parameter `T` - -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 4a462c328bf64..5fa6423306c5a 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error: generic parameters may not be used in const operations - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44 | LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` @@ -15,11 +15,12 @@ LL | struct Foo()]>(T, U); = note: type parameters may not be used in const expressions = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index c7be8bdaf9c3d..76c1b84aef557 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -1,15 +1,12 @@ // revisions: full min - #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] struct Foo()]>(T, U); -//[full]~^ ERROR constant values inside of type parameter defaults -//[min]~^^ ERROR generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations -// FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); -//~^ ERROR constant values inside of type parameter defaults +//~^ ERROR generic parameters with a default cannot use forward declared identifiers //~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/consts/const-fn-not-in-trait.rs b/src/test/ui/consts/const-fn-not-in-trait.rs index 1006d854688a4..cbc220a1ba29b 100644 --- a/src/test/ui/consts/const-fn-not-in-trait.rs +++ b/src/test/ui/consts/const-fn-not-in-trait.rs @@ -1,5 +1,5 @@ // Test that const fn is illegal in a trait declaration, whether or -// not a default is provided. +// not a default is provided, and even with the feature gate. #![feature(const_fn)] diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.rs b/src/test/ui/feature-gates/feature-gate-const_fn.rs index 691c367aeb859..b97aa214f843a 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-const_fn.rs @@ -3,10 +3,8 @@ const fn foo() -> usize { 0 } // ok trait Foo { - const fn foo() -> u32; //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const - const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const } impl Foo for u32 { diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.stderr b/src/test/ui/feature-gates/feature-gate-const_fn.stderr index 843e56301375a..1e7fd669b1d48 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_fn.stderr @@ -5,36 +5,17 @@ LL | const fn foo() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-const_fn.rs:8:5 + --> $DIR/feature-gate-const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-const_fn.rs:13:5 + --> $DIR/feature-gate-const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } | ^^^^^ functions in traits cannot be const -error[E0658]: const fn is unstable - --> $DIR/feature-gate-const_fn.rs:6:5 - | -LL | const fn foo() -> u32; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0658]: const fn is unstable - --> $DIR/feature-gate-const_fn.rs:8:5 - | -LL | const fn bar() -> u32 { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0379, E0658. -For more information about an error, try `rustc --explain E0379`. +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs index 5a01e053ed038..8f9b433009d3c 100644 --- a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs @@ -3,10 +3,8 @@ const fn foo() -> usize { 0 } // stabilized trait Foo { - const fn foo() -> u32; //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const - const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const } impl Foo for u32 { diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr index 56a882e30fc4a..d7a58591364ed 100644 --- a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr @@ -5,36 +5,17 @@ LL | const fn foo() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-min_const_fn.rs:8:5 + --> $DIR/feature-gate-min_const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-min_const_fn.rs:13:5 + --> $DIR/feature-gate-min_const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } | ^^^^^ functions in traits cannot be const -error[E0658]: const fn is unstable - --> $DIR/feature-gate-min_const_fn.rs:6:5 - | -LL | const fn foo() -> u32; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0658]: const fn is unstable - --> $DIR/feature-gate-min_const_fn.rs:8:5 - | -LL | const fn bar() -> u32 { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0379, E0658. -For more information about an error, try `rustc --explain E0379`. +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index cb2bb2832b70e..16ea71d48c825 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -5,5 +5,6 @@ struct Vec(A, T); struct Foo, C>(A, B, C); //~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index 6d76861750335..713ba091b861c 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing LL | struct Foo, C>(A, B, C); | ^ -error: aborting due to 2 previous errors +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/generic-non-trailing-defaults.rs:6:23 + | +LL | struct Foo, C>(A, B, C); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr index d24336883e963..2913a955dce1b 100644 --- a/src/test/ui/hygiene/trait_items.stderr +++ b/src/test/ui/hygiene/trait_items.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `f` found for unit type `()` in the current scope --> $DIR/trait_items.rs:17:24 | +LL | fn f(&self) {} + | - the method is available for `()` here +... LL | fn f() { ::baz::m!(); } | ------------ in this macro invocation ... diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 64ddcb81c0a9b..b993115502fd5 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -37,6 +37,9 @@ LL | use no_method_suggested_traits::Reexported; error[E0599]: no method named `method` found for type `char` in the current scope --> $DIR/no-method-suggested-traits.rs:30:9 | +LL | fn method(&self) {} + | ------ the method is available for `char` here +... LL | 'a'.method(); | ^^^^^^ method not found in `char` | @@ -63,6 +66,11 @@ error[E0599]: no method named `method` found for type `i32` in the current scope | LL | 1i32.method(); | ^^^^^^ method not found in `i32` + | + ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12 + | +LL | fn method(&self) {} + | ------ the method is available for `i32` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr index 3f63cb8e78fba..3a3767c349d65 100644 --- a/src/test/ui/issues/issue-43189.stderr +++ b/src/test/ui/issues/issue-43189.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope | LL | ().a(); | ^ method not found in `()` + | + ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8 + | +LL | fn a(&self) {} + | - the method is available for `()` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr index ee3f609f47dca..e6b0fffce663d 100644 --- a/src/test/ui/issues/issue-56175.stderr +++ b/src/test/ui/issues/issue-56175.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the | LL | reexported_trait::FooStruct.trait_method(); | ^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:3:12 + | +LL | fn trait_method(&self) { + | ------------ the method is available for `FooStruct` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: @@ -15,6 +20,11 @@ error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in t | LL | reexported_trait::FooStruct.trait_method_b(); | ^^^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:7:12 + | +LL | fn trait_method_b(&self) { + | -------------- the method is available for `FooStruct` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/loops/loop-no-implicit-break.rs b/src/test/ui/loops/loop-no-implicit-break.rs new file mode 100644 index 0000000000000..93078cb4b144b --- /dev/null +++ b/src/test/ui/loops/loop-no-implicit-break.rs @@ -0,0 +1,31 @@ +fn main() { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; +} + +fn foo() -> i8 { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; + + loop { + 1 //~ ERROR mismatched types + } + + loop { + return 1; + } + + loop { + 1 //~ ERROR mismatched types + } +} diff --git a/src/test/ui/loops/loop-no-implicit-break.stderr b/src/test/ui/loops/loop-no-implicit-break.stderr new file mode 100644 index 0000000000000..5087662e7bfa4 --- /dev/null +++ b/src/test/ui/loops/loop-no-implicit-break.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:3:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | ^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:13:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | ^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:21:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ^^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:29:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ^^^^^^ ^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/issue-82392.rs b/src/test/ui/match/issue-82392.rs new file mode 100644 index 0000000000000..d26d883040b48 --- /dev/null +++ b/src/test/ui/match/issue-82392.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() { + if true { + } else if let Some(a) = Some(3) { + } +} diff --git a/src/test/ui/match/issue-82392.stdout b/src/test/ui/match/issue-82392.stdout new file mode 100644 index 0000000000000..8ff76c64fc789 --- /dev/null +++ b/src/test/ui/match/issue-82392.stdout @@ -0,0 +1,20 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() ({ + (if (true as bool) + ({ } as + ()) else {match ((Some as + fn(i32) -> Option {Option::::Some})((3 + as + i32)) + as Option) { + Some(a) => { } + _ => { } + }} as ()) + } as ()) diff --git a/src/test/ui/match/issue-84434.rs b/src/test/ui/match/issue-84434.rs new file mode 100644 index 0000000000000..423481fd5f02d --- /dev/null +++ b/src/test/ui/match/issue-84434.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/84434 +// check-pass + +use std::path::Path; +struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, +}; + +fn main() {} diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index 4b1898345a32e..2cf5a073fe5c2 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foobar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:22:11 | +LL | fn foobar(&self) { } + | ------ the method is available for `u32` here +... LL | x.foobar(); | ^^^^^^ method not found in `u32` | @@ -11,6 +14,9 @@ LL | x.foobar(); error[E0599]: no method named `bar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:28:7 | +LL | fn bar(&self) { } + | --- the method is available for `u32` here +... LL | x.bar(); | ^^^ method not found in `u32` | diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr index 362907ecbd7ef..c3b9084affdb3 100644 --- a/src/test/ui/shadowed/shadowed-trait-methods.stderr +++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `f` found for unit type `()` in the current scope --> $DIR/shadowed-trait-methods.rs:13:8 | +LL | pub trait T { fn f(&self) {} } + | - the method is available for `()` here +... LL | ().f() | ^ method not found in `()` | diff --git a/src/test/ui/suggestions/import-trait-for-method-call.rs b/src/test/ui/suggestions/import-trait-for-method-call.rs new file mode 100644 index 0000000000000..646f68dea14e8 --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.rs @@ -0,0 +1,9 @@ +use std::hash::BuildHasher; + +fn next_u64() -> u64 { + let bh = std::collections::hash_map::RandomState::new(); + let h = bh.build_hasher(); + h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` +} + +fn main() {} diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr new file mode 100644 index 0000000000000..f3ae20552f3d5 --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope + --> $DIR/import-trait-for-method-call.rs:6:7 + | +LL | h.finish() + | ^^^^^^ method not found in `DefaultHasher` + | + ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL + | +LL | fn finish(&self) -> u64; + | ------ the method is available for `DefaultHasher` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::hash::Hasher; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index 68d527dc786aa..30daf8e277024 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -20,6 +20,9 @@ error[E0599]: no method named `b` found for struct `S` in the current scope LL | struct S; | --------- method `b` not found for this ... +LL | fn b(&self) { } + | - the method is available for `S` here +... LL | S.b(); | ^ method not found in `S` | diff --git a/src/tools/miri b/src/tools/miri index a86eab3e6c3d6..58436e942a9f3 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit a86eab3e6c3d645769bfdb2d09efd84d1e1fcbc0 +Subproject commit 58436e942a9f301748a2d7e88e6184e168cfcfbd