Auto merge of #67764 - Centril:rollup-ycbq3os, r=Centril

Rollup of 6 pull requests

Successful merges:

 - #67574 (Extract `rustc_ast_lowering` crate from `rustc`)
 - #67685 (Constify Result)
 - #67702 (Add symbol normalization for proc_macro_server.)
 - #67730 (Cleanup pattern type checking, fix diagnostics bugs (+ improvements))
 - #67744 (parser: reduce diversity in error handling mechanisms)
 - #67748 (Use function attribute "frame-pointer" instead of "no-frame-pointer-elim")

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-12-31 19:41:36 +00:00
commit 119307a83e
86 changed files with 730 additions and 508 deletions

View File

@ -3358,6 +3358,22 @@ dependencies = [
"core",
]
[[package]]
name = "rustc_ast_lowering"
version = "0.0.0"
dependencies = [
"log",
"rustc",
"rustc_data_structures",
"rustc_error_codes",
"rustc_errors",
"rustc_index",
"rustc_span",
"rustc_target",
"smallvec 1.0.0",
"syntax",
]
[[package]]
name = "rustc_builtin_macros"
version = "0.0.0"
@ -3578,6 +3594,7 @@ dependencies = [
"once_cell",
"rustc",
"rustc-rayon",
"rustc_ast_lowering",
"rustc_builtin_macros",
"rustc_codegen_llvm",
"rustc_codegen_ssa",
@ -3783,6 +3800,7 @@ dependencies = [
"bitflags",
"log",
"rustc",
"rustc_ast_lowering",
"rustc_data_structures",
"rustc_error_codes",
"rustc_errors",

View File

@ -76,6 +76,7 @@
#![feature(const_fn_union)]
#![feature(const_generics)]
#![feature(const_ptr_offset_from)]
#![feature(const_result)]
#![feature(const_type_name)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]

View File

@ -278,9 +278,10 @@ impl<T, E> Result<T, E> {
/// assert_eq!(x.is_ok(), false);
/// ```
#[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
#[rustc_const_unstable(feature = "const_result", issue = "67520")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_ok(&self) -> bool {
pub const fn is_ok(&self) -> bool {
match *self {
Ok(_) => true,
Err(_) => false,
@ -303,9 +304,10 @@ impl<T, E> Result<T, E> {
/// assert_eq!(x.is_err(), true);
/// ```
#[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
#[rustc_const_unstable(feature = "const_result", issue = "67520")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_err(&self) -> bool {
pub const fn is_err(&self) -> bool {
!self.is_ok()
}
@ -446,8 +448,9 @@ impl<T, E> Result<T, E> {
/// assert_eq!(x.as_ref(), Err(&"Error"));
/// ```
#[inline]
#[rustc_const_unstable(feature = "const_result", issue = "67520")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_ref(&self) -> Result<&T, &E> {
pub const fn as_ref(&self) -> Result<&T, &E> {
match *self {
Ok(ref x) => Ok(x),
Err(ref x) => Err(x),

View File

@ -39,7 +39,6 @@ pub mod def;
pub mod def_id;
pub mod intravisit;
pub mod itemlikevisit;
pub mod lowering;
pub mod map;
pub mod pat_util;
pub mod print;
@ -599,7 +598,7 @@ pub enum SyntheticTyParamKind {
pub struct WhereClause<'hir> {
pub predicates: &'hir [WherePredicate<'hir>],
// Only valid if predicates isn't empty.
span: Span,
pub span: Span,
}
impl WhereClause<'_> {

View File

@ -581,10 +581,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
) {
match cause.code {
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
let ty = self.resolve_vars_if_possible(&root_ty);
if ty.is_suggestable() {
// don't show type `_`
err.span_label(span, format!("this match expression has type `{}`", ty));
err.span_label(span, format!("this expression has type `{}`", ty));
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
if ty.is_box() && ty.boxed_ty() == found {
@ -599,11 +600,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
}
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
err.span_label(span, "expected due to this");
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
source,
ref prior_arms,
last_ty,
discrim_hir_id,
scrut_hir_id,
..
}) => match source {
hir::MatchSource::IfLetDesugar { .. } => {
@ -612,16 +616,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
hir::MatchSource::TryDesugar => {
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
let discrim_expr = self.tcx.hir().expect_expr(discrim_hir_id);
let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.kind {
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
let arg_expr = args.first().expect("try desugaring call w/out arg");
self.in_progress_tables
.and_then(|tables| tables.borrow().expr_ty_opt(arg_expr))
} else {
bug!("try desugaring w/out call expr as discriminant");
bug!("try desugaring w/out call expr as scrutinee");
};
match discrim_ty {
match scrut_ty {
Some(ty) if expected == ty => {
let source_map = self.tcx.sess.source_map();
err.span_suggestion(

View File

@ -28,7 +28,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(arbitrary_self_types)]
#![feature(array_value_iter)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]

View File

@ -523,7 +523,7 @@ pub enum BuiltinLintDiagnostics {
DeprecatedMacro(Option<Symbol>, Span),
}
pub(crate) fn add_elided_lifetime_in_path_suggestion(
pub fn add_elided_lifetime_in_path_suggestion(
sess: &Session,
db: &mut DiagnosticBuilder<'_>,
n: usize,

View File

@ -2580,7 +2580,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
match *cause_code {
ObligationCauseCode::ExprAssignable
| ObligationCauseCode::MatchExpressionArm { .. }
| ObligationCauseCode::MatchExpressionArmPattern { .. }
| ObligationCauseCode::Pattern { .. }
| ObligationCauseCode::IfExpression { .. }
| ObligationCauseCode::IfExpressionWithNoElse
| ObligationCauseCode::MainFunctionType

View File

@ -249,10 +249,14 @@ pub enum ObligationCauseCode<'tcx> {
/// Computing common supertype in the arms of a match expression
MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),
/// Computing common supertype in the pattern guard for the arms of a match expression
MatchExpressionArmPattern {
span: Span,
ty: Ty<'tcx>,
/// Type error arising from type checking a pattern against an expected type.
Pattern {
/// The span of the scrutinee or type expression which caused the `root_ty` type.
span: Option<Span>,
/// The root expected type induced by a scrutinee or type expression.
root_ty: Ty<'tcx>,
/// Whether the `Span` came from an expression or a type expression.
origin_expr: bool,
},
/// Constants in patterns must have `Structural` type.
@ -311,7 +315,7 @@ pub struct MatchExpressionArmCause<'tcx> {
pub source: hir::MatchSource,
pub prior_arms: Vec<Span>,
pub last_ty: Ty<'tcx>,
pub discrim_hir_id: hir::HirId,
pub scrut_hir_id: hir::HirId,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]

View File

@ -511,18 +511,18 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
source,
ref prior_arms,
last_ty,
discrim_hir_id,
scrut_hir_id,
}) => tcx.lift(&last_ty).map(|last_ty| {
super::MatchExpressionArm(box super::MatchExpressionArmCause {
arm_span,
source,
prior_arms: prior_arms.clone(),
last_ty,
discrim_hir_id,
scrut_hir_id,
})
}),
super::MatchExpressionArmPattern { span, ty } => {
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
super::Pattern { span, root_ty, origin_expr } => {
tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
}
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))

View File

@ -0,0 +1,22 @@
[package]
authors = ["The Rust Project Developers"]
name = "rustc_ast_lowering"
version = "0.0.0"
edition = "2018"
[lib]
name = "rustc_ast_lowering"
path = "lib.rs"
doctest = false
[dependencies]
log = { version = "0.4", features = ["release_max_level_info", "std"] }
rustc = { path = "../librustc" }
rustc_target = { path = "../librustc_target" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_index = { path = "../librustc_index" }
rustc_span = { path = "../librustc_span" }
rustc_error_codes = { path = "../librustc_error_codes" }
rustc_errors = { path = "../librustc_errors" }
syntax = { path = "../libsyntax" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }

View File

@ -1,16 +1,16 @@
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
use crate::hir;
use crate::hir::def::Res;
use rustc::bug;
use rustc::hir;
use rustc::hir::def::Res;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_error_codes::*;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
use rustc_span::symbol::{sym, Symbol};
use syntax::ast::*;
use syntax::attr;
use syntax::ptr::P as AstP;
use syntax::source_map::{respan, DesugaringKind, Span, Spanned};
use syntax::symbol::{sym, Symbol};
use rustc_error_codes::*;
use syntax::{span_err, struct_span_err};
impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@ -82,11 +82,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label)
}),
ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
hir::ExprKind::Loop(
this.lower_block(body, false),
this.lower_label(opt_label),
hir::LoopSource::Loop,
)
hir::ExprKind::Loop(this.lower_block(body, false), opt_label, hir::LoopSource::Loop)
}),
ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match(
@ -123,10 +119,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_expr_closure(capture_clause, movability, decl, body, fn_decl_span)
}
}
ExprKind::Block(ref blk, opt_label) => hir::ExprKind::Block(
self.lower_block(blk, opt_label.is_some()),
self.lower_label(opt_label),
),
ExprKind::Block(ref blk, opt_label) => {
hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
}
ExprKind::Assign(ref el, ref er, span) => {
hir::ExprKind::Assign(self.lower_expr(el), self.lower_expr(er), span)
}
@ -407,11 +402,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
// `[opt_ident]: loop { ... }`
hir::ExprKind::Loop(
self.block_expr(self.arena.alloc(match_expr)),
self.lower_label(opt_label),
source,
)
hir::ExprKind::Loop(self.block_expr(self.arena.alloc(match_expr)), opt_label, source)
}
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
@ -836,10 +827,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
fn lower_label(&mut self, label: Option<Label>) -> Option<hir::Label> {
label.map(|label| hir::Label { ident: label.ident })
}
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
let target_id = match destination {
Some((id, _)) => {
@ -857,7 +844,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
.into(),
};
hir::Destination { label: self.lower_label(destination.map(|(_, label)| label)), target_id }
hir::Destination { label: destination.map(|(_, label)| label), target_id }
}
fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
@ -1100,8 +1087,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
// `[opt_ident]: loop { ... }`
let kind =
hir::ExprKind::Loop(loop_block, self.lower_label(opt_label), hir::LoopSource::ForLoop);
let kind = hir::ExprKind::Loop(loop_block, opt_label, hir::LoopSource::ForLoop);
let loop_expr = self.arena.alloc(hir::Expr {
hir_id: self.lower_node_id(e.id),
kind,

View File

@ -1,28 +1,25 @@
use super::AnonymousLifetimeMode;
use super::ImplTraitContext;
use super::ImplTraitPosition;
use super::ImplTraitTypeIdVisitor;
use super::LoweringContext;
use super::ParamMode;
use crate::arena::Arena;
use crate::hir;
use crate::hir::def::{DefKind, Res};
use crate::hir::def_id::DefId;
use crate::util::nodemap::NodeMap;
use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
use super::{ImplTraitContext, ImplTraitPosition, ImplTraitTypeIdVisitor};
use rustc::arena::Arena;
use rustc::bug;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::hir::def_id::DefId;
use rustc::util::nodemap::NodeMap;
use rustc_error_codes::*;
use rustc_span::source_map::{respan, DesugaringKind};
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
use rustc_target::spec::abi;
use smallvec::SmallVec;
use std::collections::BTreeSet;
use syntax::ast::*;
use syntax::attr;
use syntax::source_map::{respan, DesugaringKind};
use syntax::symbol::{kw, sym};
use syntax::struct_span_err;
use syntax::visit::{self, Visitor};
use syntax_pos::Span;
use rustc_error_codes::*;
use log::debug;
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeSet;
pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
@ -1429,7 +1426,7 @@ pub(super) struct GenericsCtor<'hir> {
span: Span,
}
impl GenericsCtor<'hir> {
impl<'hir> GenericsCtor<'hir> {
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> hir::Generics<'hir> {
hir::Generics {
params: arena.alloc_from_iter(self.params),

View File

@ -32,45 +32,47 @@
//! get confused if the spans from leaf AST nodes occur in multiple places
//! in the HIR, especially for multiple identifiers.
use crate::arena::Arena;
use crate::dep_graph::DepGraph;
use crate::hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use crate::hir::map::{DefKey, DefPathData, Definitions};
use crate::hir::{self, ParamName};
use crate::hir::{ConstArg, GenericArg};
use crate::lint;
use crate::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
use crate::middle::cstore::CrateStore;
use crate::session::config::nightly_options;
use crate::session::Session;
use crate::util::captures::Captures;
use crate::util::common::FN_OUTPUT_NAME;
use crate::util::nodemap::{DefIdMap, NodeMap};
use errors::Applicability;
#![feature(array_value_iter)]
use rustc::arena::Arena;
use rustc::dep_graph::DepGraph;
use rustc::hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::map::{DefKey, DefPathData, Definitions};
use rustc::hir::{self, ConstArg, GenericArg, ParamName};
use rustc::lint;
use rustc::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
use rustc::middle::cstore::CrateStore;
use rustc::session::config::nightly_options;
use rustc::session::Session;
use rustc::util::captures::Captures;
use rustc::util::common::FN_OUTPUT_NAME;
use rustc::util::nodemap::{DefIdMap, NodeMap};
use rustc::{bug, span_bug};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use rustc_error_codes::*;
use rustc_errors::Applicability;
use rustc_index::vec::IndexVec;
use smallvec::SmallVec;
use std::collections::BTreeMap;
use std::mem;
use rustc_span::hygiene::ExpnId;
use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind, Spanned};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use syntax::ast;
use syntax::ast::*;
use syntax::attr;
use syntax::errors;
use syntax::print::pprust;
use syntax::ptr::P as AstP;
use syntax::sess::ParseSess;
use syntax::source_map::{respan, DesugaringKind, ExpnData, ExpnKind, Spanned};
use syntax::symbol::{kw, sym, Symbol};
use syntax::token::{self, Nonterminal, Token};
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::visit::{self, Visitor};
use syntax_pos::hygiene::ExpnId;
use syntax_pos::Span;
use syntax::{help, struct_span_err, walk_list};
use rustc_error_codes::*;
use log::{debug, trace};
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeMap;
use std::mem;
macro_rules! arena_vec {
($this:expr; $($x:expr),*) => ({
@ -84,7 +86,7 @@ mod item;
const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
pub struct LoweringContext<'a, 'hir: 'a> {
struct LoweringContext<'a, 'hir: 'a> {
crate_root: Option<Symbol>,
/// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
@ -235,13 +237,13 @@ enum ImplTraitPosition {
Other,
}
impl<'b, 'a> ImplTraitContext<'b, 'a> {
impl<'a> ImplTraitContext<'_, 'a> {
#[inline]
fn disallowed() -> Self {
ImplTraitContext::Disallowed(ImplTraitPosition::Other)
}
fn reborrow(&'c mut self) -> ImplTraitContext<'c, 'a> {
fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'a> {
use self::ImplTraitContext::*;
match self {
Universal(params) => Universal(params),
@ -372,8 +374,8 @@ struct ImplTraitTypeIdVisitor<'a> {
ids: &'a mut SmallVec<[NodeId; 1]>,
}
impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> {
fn visit_ty(&mut self, ty: &'a Ty) {
impl Visitor<'_> for ImplTraitTypeIdVisitor<'_> {
fn visit_ty(&mut self, ty: &Ty) {
match ty.kind {
TyKind::Typeof(_) | TyKind::BareFn(_) => return,
@ -383,7 +385,7 @@ impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> {
visit::walk_ty(self, ty);
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
fn visit_path_segment(&mut self, path_span: Span, path_segment: &PathSegment) {
if let Some(ref p) = path_segment.args {
if let GenericArgs::Parenthesized(_) = **p {
return;
@ -687,7 +689,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.resolver.get_import_res(id).present_items()
}
fn diagnostic(&self) -> &errors::Handler {
fn diagnostic(&self) -> &rustc_errors::Handler {
self.sess.diagnostic()
}
@ -3288,7 +3290,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId> {
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {
// Sorting by span ensures that we get things in order within a
// file, and also puts the files in a sensible order.
let mut body_ids: Vec<_> = bodies.keys().cloned().collect();
@ -3303,7 +3305,7 @@ struct GenericArgsCtor<'hir> {
parenthesized: bool,
}
impl GenericArgsCtor<'hir> {
impl<'hir> GenericArgsCtor<'hir> {
fn is_empty(&self) -> bool {
self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
}

View File

@ -66,12 +66,21 @@ fn naked(val: &'ll Value, is_naked: bool) {
pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
if cx.sess().must_not_eliminate_frame_pointers() {
llvm::AddFunctionAttrStringValue(
llfn,
llvm::AttributePlace::Function,
const_cstr!("no-frame-pointer-elim"),
const_cstr!("true"),
);
if llvm_util::get_major_version() >= 8 {
llvm::AddFunctionAttrStringValue(
llfn,
llvm::AttributePlace::Function,
const_cstr!("frame-pointer"),
const_cstr!("all"),
);
} else {
llvm::AddFunctionAttrStringValue(
llfn,
llvm::AttributePlace::Function,
const_cstr!("no-frame-pointer-elim"),
const_cstr!("true"),
);
}
}
}

View File

@ -890,12 +890,12 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
Ok(match name {
sym::item => match p.parse_item()? {
Some(i) => token::NtItem(i),
None => return Err(p.fatal("expected an item keyword")),
None => return Err(p.struct_span_err(p.token.span, "expected an item keyword")),
},
sym::block => token::NtBlock(p.parse_block()?),
sym::stmt => match p.parse_stmt()? {
Some(s) => token::NtStmt(s),
None => return Err(p.fatal("expected a statement")),
None => return Err(p.struct_span_err(p.token.span, "expected a statement")),
},
sym::pat => token::NtPat(p.parse_pat(None)?),
sym::expr => token::NtExpr(p.parse_expr()?),
@ -909,7 +909,8 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
token::NtIdent(Ident::new(name, span), is_raw)
} else {
let token_str = pprust::token_to_string(&p.token);
return Err(p.fatal(&format!("expected ident, found {}", &token_str)));
let msg = &format!("expected ident, found {}", &token_str);
return Err(p.struct_span_err(p.token.span, msg));
}
}
sym::path => token::NtPath(p.parse_path(PathStyle::Type)?),
@ -920,7 +921,8 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
token::NtLifetime(p.expect_lifetime().ident)
} else {
let token_str = pprust::token_to_string(&p.token);
return Err(p.fatal(&format!("expected a lifetime, found `{}`", &token_str)));
let msg = &format!("expected a lifetime, found `{}`", &token_str);
return Err(p.struct_span_err(p.token.span, msg));
}
}
// this is not supposed to happen, since it has been checked

View File

@ -1,5 +1,6 @@
use crate::base::ExtCtxt;
use rustc_parse::lexer::nfc_normalize;
use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
use syntax::ast;
use syntax::print::pprust;
@ -327,6 +328,7 @@ impl Ident {
}
}
fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
let sym = nfc_normalize(&sym.as_str());
let string = sym.as_str();
if !Self::is_valid(&string) {
panic!("`{:?}` is not a valid identifier", string)

View File

@ -20,6 +20,7 @@ rustc_parse = { path = "../librustc_parse" }
syntax_pos = { path = "../librustc_span", package = "rustc_span" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
rustc = { path = "../librustc" }
rustc_ast_lowering = { path = "../librustc_ast_lowering" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_traits = { path = "../librustc_traits" }
rustc_data_structures = { path = "../librustc_data_structures" }

View File

@ -7,7 +7,6 @@ use rustc::arena::Arena;
use rustc::dep_graph::DepGraph;
use rustc::hir;
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc::hir::lowering::lower_crate;
use rustc::lint;
use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
use rustc::middle::{self, stability};
@ -442,8 +441,14 @@ pub fn lower_to_hir<'res, 'tcx>(
) -> Result<hir::map::Forest<'tcx>> {
// Lower AST to HIR.
let hir_forest = time(sess, "lowering AST -> HIR", || {
let nt_to_tokenstream = rustc_parse::nt_to_tokenstream;
let hir_crate = lower_crate(sess, &dep_graph, &krate, resolver, nt_to_tokenstream, arena);
let hir_crate = rustc_ast_lowering::lower_crate(
sess,
&dep_graph,
&krate,
resolver,
rustc_parse::nt_to_tokenstream,
arena,
);
if sess.opts.debugging_opts.hir_stats {
hir_stats::print_hir_stats(&hir_crate);

View File

@ -16,8 +16,8 @@ use std::{f32, f64, i16, i32, i64, i8, u16, u32, u64, u8};
use rustc_target::spec::abi::Abi;
use syntax::errors::Applicability;
use syntax::symbol::sym;
use syntax::{ast, attr, source_map};
use syntax_pos::symbol::sym;
use syntax_pos::Span;
use rustc::hir;

View File

@ -220,7 +220,7 @@ impl<'a> StringReader<'a> {
if is_raw_ident {
ident_start = ident_start + BytePos(2);
}
let sym = self.nfc_symbol_from(ident_start);
let sym = nfc_normalize(self.str_from(ident_start));
if is_raw_ident {
let span = self.mk_sp(start, self.pos);
if !sym.can_be_raw() {
@ -469,20 +469,6 @@ impl<'a> StringReader<'a> {
Symbol::intern(self.str_from_to(start, end))
}
/// As symbol_from, with the text normalized into Unicode NFC form.
fn nfc_symbol_from(&self, start: BytePos) -> Symbol {
use unicode_normalization::{is_nfc_quick, IsNormalized, UnicodeNormalization};
debug!("taking an normalized ident from {:?} to {:?}", start, self.pos);
let sym = self.str_from(start);
match is_nfc_quick(sym.chars()) {
IsNormalized::Yes => Symbol::intern(sym),
_ => {
let sym_str: String = sym.chars().nfc().collect();
Symbol::intern(&sym_str)
}
}
}
/// Slice of the source text spanning from `start` up to but excluding `end`.
fn str_from_to(&self, start: BytePos, end: BytePos) -> &str {
&self.src[self.src_index(start)..self.src_index(end)]
@ -651,3 +637,14 @@ impl<'a> StringReader<'a> {
}
}
}
pub fn nfc_normalize(string: &str) -> Symbol {
use unicode_normalization::{is_nfc_quick, IsNormalized, UnicodeNormalization};
match is_nfc_quick(string.chars()) {
IsNormalized::Yes => Symbol::intern(string),
_ => {
let normalized_str: String = string.chars().nfc().collect();
Symbol::intern(&normalized_str)
}
}
}

View File

@ -46,7 +46,8 @@ impl<'a> Parser<'a> {
token::DocComment(s) => {
let attr = self.mk_doc_comment(s);
if attr.style != ast::AttrStyle::Outer {
let mut err = self.fatal("expected outer doc comment");
let span = self.token.span;
let mut err = self.struct_span_err(span, "expected outer doc comment");
err.note(
"inner doc comments like this (starting with \
`//!` or `/*!`) can only appear before items",
@ -133,7 +134,7 @@ impl<'a> Parser<'a> {
"previous outer attribute"
};
let mut diagnostic = self.diagnostic().struct_span_err(attr_sp, reason);
let mut diagnostic = self.struct_span_err(attr_sp, reason);
if let Some(prev_attr_sp) = prev_attr_sp {
diagnostic
@ -156,7 +157,8 @@ impl<'a> Parser<'a> {
}
_ => {
let token_str = pprust::token_to_string(&self.token);
return Err(self.fatal(&format!("expected `#`, found `{}`", token_str)));
let msg = &format!("expected `#`, found `{}`", token_str);
return Err(self.struct_span_err(self.token.span, msg));
}
};
@ -231,8 +233,7 @@ impl<'a> Parser<'a> {
if !lit.kind.is_unsuffixed() {
let msg = "suffixed literals are not allowed in attributes";
self.diagnostic()
.struct_span_err(lit.span, msg)
self.struct_span_err(lit.span, msg)
.help(
"instead of using a suffixed literal \
(1u8, 1.0f32, etc.), use an unsuffixed version \
@ -332,6 +333,6 @@ impl<'a> Parser<'a> {
let found = pprust::token_to_string(&self.token);
let msg = format!("expected unsuffixed literal or identifier, found `{}`", found);
Err(self.diagnostic().struct_span_err(self.token.span, &msg))
Err(self.struct_span_err(self.token.span, &msg))
}
}

View File

@ -157,14 +157,6 @@ crate enum ConsumeClosingDelim {
}
impl<'a> Parser<'a> {
pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
self.span_fatal(self.token.span, m)
}
crate fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
self.sess.span_diagnostic.struct_span_fatal(sp, m)
}
pub(super) fn span_fatal_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -173,14 +165,6 @@ impl<'a> Parser<'a> {
err.span_err(sp, self.diagnostic())
}
pub(super) fn bug(&self, m: &str) -> ! {
self.sess.span_diagnostic.span_bug(self.token.span, m)
}
pub(super) fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
self.sess.span_diagnostic.span_err(sp, m)
}
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
self.sess.span_diagnostic.struct_span_err(sp, m)
}
@ -298,7 +282,7 @@ impl<'a> Parser<'a> {
)
};
self.last_unexpected_token_span = Some(self.token.span);
let mut err = self.fatal(&msg_exp);
let mut err = self.struct_span_err(self.token.span, &msg_exp);
let sp = if self.token == token::Eof {
// This is EOF; don't want to point at the following char, but rather the last token.
self.prev_span
@ -502,18 +486,17 @@ impl<'a> Parser<'a> {
let span = lo.until(self.token.span);
let total_num_of_gt = number_of_gt + number_of_shr * 2;
self.diagnostic()
.struct_span_err(
span,
&format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
)
.span_suggestion(
span,
&format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
String::new(),
Applicability::MachineApplicable,
)
.emit();
self.struct_span_err(
span,
&format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
)
.span_suggestion(
span,
&format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
}
@ -762,8 +745,7 @@ impl<'a> Parser<'a> {
path.span = ty_span.to(self.prev_span);
let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
self.diagnostic()
.struct_span_err(path.span, "missing angle brackets in associated item path")
self.struct_span_err(path.span, "missing angle brackets in associated item path")
.span_suggestion(
// This is a best-effort recovery.
path.span,
@ -1271,7 +1253,8 @@ impl<'a> Parser<'a> {
pub(super) fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> {
let token_str = super::token_descr(&self.token);
let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
let msg = &format!("expected `;` or `{{`, found {}", token_str);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected `;` or `{`");
Err(err)
}

View File

@ -283,7 +283,7 @@ impl<'a> Parser<'a> {
self.mk_expr(span, aopexpr, AttrVec::new())
}
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
self.bug("AssocOp should have been handled by special case")
self.span_bug(span, "AssocOp should have been handled by special case")
}
};
@ -822,7 +822,11 @@ impl<'a> Parser<'a> {
} else {
// Field access `expr.f`
if let Some(args) = segment.args {
self.span_err(args.span(), "field expressions may not have generic arguments");
self.struct_span_err(
args.span(),
"field expressions may not have generic arguments",
)
.emit();
}
let span = lo.to(self.prev_span);
@ -1133,7 +1137,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
self.parse_opt_lit().ok_or_else(|| {
let msg = format!("unexpected token: {}", super::token_descr(&self.token));
self.span_fatal(self.token.span, &msg)
self.struct_span_err(self.token.span, &msg)
})
}
@ -1446,9 +1450,7 @@ impl<'a> Parser<'a> {
self.struct_span_err(sp, "missing condition for `if` expression")
.span_label(sp, "expected if condition here")
.emit();
let expr = self.mk_expr_err(span);
let stmt = self.mk_stmt(span, ast::StmtKind::Expr(expr));
self.mk_block(vec![stmt], BlockCheckMode::Default, span)
self.mk_block_err(span)
}
/// Parses the condition of a `if` or `while` expression.
@ -1915,8 +1917,7 @@ impl<'a> Parser<'a> {
return;
}
self.diagnostic()
.struct_span_err(self.token.span, "expected `:`, found `=`")
self.struct_span_err(self.token.span, "expected `:`, found `=`")
.span_suggestion(
field_name.span.shrink_to_hi().to(self.token.span),
"replace equals symbol with a colon",

View File

@ -306,8 +306,7 @@ impl<'a> Parser<'a> {
// possible public struct definition where `struct` was forgotten
let ident = self.parse_ident().unwrap();
let msg = format!("add `struct` here to parse `{}` as a public struct", ident);
let mut err =
self.diagnostic().struct_span_err(sp, "missing `struct` for struct definition");
let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
err.span_suggestion_short(
sp,
&msg,
@ -335,7 +334,7 @@ impl<'a> Parser<'a> {
};
let msg = format!("missing `{}` for {} definition", kw, kw_name);
let mut err = self.diagnostic().struct_span_err(sp, &msg);
let mut err = self.struct_span_err(sp, &msg);
if !ambiguous {
self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
let suggestion =
@ -375,7 +374,7 @@ impl<'a> Parser<'a> {
("fn` or `struct", "function or struct", true)
};
let msg = format!("missing `{}` for {} definition", kw, kw_name);
let mut err = self.diagnostic().struct_span_err(sp, &msg);
let mut err = self.struct_span_err(sp, &msg);
if !ambiguous {
err.span_suggestion_short(
sp,
@ -446,9 +445,7 @@ impl<'a> Parser<'a> {
// FAILURE TO PARSE ITEM
match visibility.node {
VisibilityKind::Inherited => {}
_ => {
return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`"));
}
_ => return Err(self.struct_span_err(self.prev_span, "unmatched visibility `pub`")),
}
if !attributes_allowed && !attrs.is_empty() {
@ -466,7 +463,7 @@ impl<'a> Parser<'a> {
_ => "expected item after attributes",
};
let mut err = self.diagnostic().struct_span_err(self.prev_span, message);
let mut err = self.struct_span_err(self.prev_span, message);
if attrs.last().unwrap().is_doc_comment() {
err.span_label(self.prev_span, "this doc comment doesn't document anything");
}
@ -536,7 +533,6 @@ impl<'a> Parser<'a> {
// ^^ `sp` below will point to this
let sp = prev_span.between(self.prev_span);
let mut err = self
.diagnostic()
.struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type));
err.span_label(sp, expected_kinds);
err
@ -619,7 +615,7 @@ impl<'a> Parser<'a> {
// This notably includes paths passed through `ty` macro fragments (#46438).
TyKind::Path(None, path) => path,
_ => {
self.span_err(ty_first.span, "expected a trait, found type");
self.struct_span_err(ty_first.span, "expected a trait, found type").emit();
err_path(ty_first.span)
}
};
@ -1349,10 +1345,11 @@ impl<'a> Parser<'a> {
body
} else {
let token_str = super::token_descr(&self.token);
let mut err = self.fatal(&format!(
let msg = &format!(
"expected `where`, `{{`, `(`, or `;` after struct name, found {}",
token_str
));
);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected `where`, `{`, `(`, or `;` after struct name");
return Err(err);
};
@ -1375,8 +1372,8 @@ impl<'a> Parser<'a> {
VariantData::Struct(fields, recovered)
} else {
let token_str = super::token_descr(&self.token);
let mut err = self
.fatal(&format!("expected `where` or `{{` after union name, found {}", token_str));
let msg = &format!("expected `where` or `{{` after union name, found {}", token_str);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected `where` or `{` after union name");
return Err(err);
};
@ -1412,10 +1409,8 @@ impl<'a> Parser<'a> {
self.eat(&token::CloseDelim(token::Brace));
} else {
let token_str = super::token_descr(&self.token);
let mut err = self.fatal(&format!(
"expected `where`, or `{{` after struct name, found {}",
token_str
));
let msg = &format!("expected `where`, or `{{` after struct name, found {}", token_str);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected `where`, or `{` after struct name");
return Err(err);
}
@ -1603,9 +1598,8 @@ impl<'a> Parser<'a> {
VisibilityKind::Inherited => {}
_ => {
let mut err = if self.token.is_keyword(sym::macro_rules) {
let mut err = self
.diagnostic()
.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
let mut err =
self.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
err.span_suggestion(
sp,
"try exporting the macro",
@ -1614,9 +1608,8 @@ impl<'a> Parser<'a> {
);
err
} else {
let mut err = self
.diagnostic()
.struct_span_err(sp, "can't qualify macro invocation with `pub`");
let mut err =
self.struct_span_err(sp, "can't qualify macro invocation with `pub`");
err.help("try adjusting the macro to put `pub` inside the invocation");
err
};

View File

@ -884,7 +884,8 @@ impl<'a> Parser<'a> {
pub fn bump(&mut self) {
if self.prev_token_kind == PrevTokenKind::Eof {
// Bumping after EOF is a bad sign, usually an infinite loop.
self.bug("attempted to bump the parser past EOF (may be stuck in a loop)");
let msg = "attempted to bump the parser past EOF (may be stuck in a loop)";
self.span_bug(self.token.span, msg);
}
self.prev_span = self.meta_var_span.take().unwrap_or(self.token.span);
@ -1056,8 +1057,7 @@ impl<'a> Parser<'a> {
_ => unreachable!(),
};
let span = self.prev_span.to(self.token.span);
self.diagnostic()
.struct_span_fatal(span, &format!("unknown macro variable `{}`", name))
self.struct_span_err(span, &format!("unknown macro variable `{}`", name))
.span_label(span, "unknown macro variable")
.emit();
self.bump();

View File

@ -81,7 +81,8 @@ impl<'a> Parser<'a> {
if !self.eat(term) {
let token_str = super::token_descr(&self.token);
if !self.maybe_consume_incorrect_semicolon(&items) {
let mut err = self.fatal(&format!("expected item, found {}", token_str));
let msg = &format!("expected item, found {}", token_str);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected item");
return Err(err);
}
@ -129,7 +130,7 @@ impl<'a> Parser<'a> {
DirectoryOwnership::UnownedViaBlock => {
let msg = "Cannot declare a non-inline module inside a block \
unless it has a path attribute";
let mut err = self.diagnostic().struct_span_err(id_sp, msg);
let mut err = self.struct_span_err(id_sp, msg);
if paths.path_exists {
let msg = format!(
"Maybe `use` the module `{}` instead of redeclaring it",
@ -140,9 +141,8 @@ impl<'a> Parser<'a> {
Err(err)
}
DirectoryOwnership::UnownedViaMod => {
let mut err = self
.diagnostic()
.struct_span_err(id_sp, "cannot declare a new module at this location");
let mut err =
self.struct_span_err(id_sp, "cannot declare a new module at this location");
if !id_sp.is_dummy() {
let src_path = self.sess.source_map().span_to_filename(id_sp);
if let FileName::Real(src_path) = src_path {
@ -263,7 +263,7 @@ impl<'a> Parser<'a> {
err.push_str(" -> ");
}
err.push_str(&path.to_string_lossy());
return Err(self.span_fatal(id_sp, &err[..]));
return Err(self.struct_span_err(id_sp, &err[..]));
}
included_mod_stack.push(path.clone());
drop(included_mod_stack);

View File

@ -673,7 +673,7 @@ impl<'a> Parser<'a> {
let expected = expected.unwrap_or("pattern");
let msg = format!("expected {}, found {}", expected, super::token_descr(&self.token));
let mut err = self.fatal(&msg);
let mut err = self.struct_span_err(self.token.span, &msg);
err.span_label(self.token.span, format!("expected {}", expected));
let sp = self.sess.source_map().start_point(self.token.span);
@ -699,8 +699,7 @@ impl<'a> Parser<'a> {
let range_span = lo.to(end.span);
let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new());
self.diagnostic()
.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
self.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
.span_suggestion(
range_span,
"try using the minimum value for the type",
@ -722,18 +721,17 @@ impl<'a> Parser<'a> {
// Parsing e.g. `X..`.
let range_span = begin.span.to(self.prev_span);
self.diagnostic()
.struct_span_err(
range_span,
&format!("`X{}` range patterns are not supported", form),
)
.span_suggestion(
range_span,
"try using the maximum value for the type",
format!("{}{}MAX", pprust::expr_to_string(&begin), form),
Applicability::HasPlaceholders,
)
.emit();
self.struct_span_err(
range_span,
&format!("`X{}` range patterns are not supported", form),
)
.span_suggestion(
range_span,
"try using the maximum value for the type",
format!("{}{}MAX", pprust::expr_to_string(&begin), form),
Applicability::HasPlaceholders,
)
.emit();
Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new()))
}
@ -798,7 +796,9 @@ impl<'a> Parser<'a> {
// binding mode then we do not end up here, because the lookahead
// will direct us over to `parse_enum_variant()`.
if self.token == token::OpenDelim(token::Paren) {
return Err(self.span_fatal(self.prev_span, "expected identifier, found enum pattern"));
return Err(
self.struct_span_err(self.prev_span, "expected identifier, found enum pattern")
);
}
Ok(PatKind::Ident(binding_mode, ident, sub))
@ -807,12 +807,8 @@ impl<'a> Parser<'a> {
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
if qself.is_some() {
let msg = "unexpected `{` after qualified path";
let mut err = self.fatal(msg);
err.span_label(self.token.span, msg);
return Err(err);
return self.error_qpath_before_pat(&path, "{");
}
self.bump();
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
e.emit();
@ -826,15 +822,22 @@ impl<'a> Parser<'a> {
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
if qself.is_some() {
let msg = "unexpected `(` after qualified path";
let mut err = self.fatal(msg);
err.span_label(self.token.span, msg);
return Err(err);
return self.error_qpath_before_pat(&path, "(");
}
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;
Ok(PatKind::TupleStruct(path, fields))
}
/// Error when there's a qualified path, e.g. `<Foo as Bar>::Baz`
/// as the path of e.g., a tuple or record struct pattern.
fn error_qpath_before_pat(&mut self, path: &Path, token: &str) -> PResult<'a, PatKind> {
let msg = &format!("unexpected `{}` after qualified path", token);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, msg);
err.span_label(path.span, "the qualified path");
Err(err)
}
/// Parses the fields of a struct-like pattern.
fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<FieldPat>, bool)> {
let mut fields = Vec::new();
@ -877,7 +880,8 @@ impl<'a> Parser<'a> {
break;
}
let token_str = super::token_descr(&self.token);
let mut err = self.fatal(&format!("expected `}}`, found {}", token_str));
let msg = &format!("expected `}}`, found {}", token_str);
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected `}`");
let mut comma_sp = None;

View File

@ -93,7 +93,7 @@ impl<'a> Parser<'a> {
maybe_whole!(self, NtPath, |path| {
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
{
self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
self.struct_span_err(path.span, "unexpected generic arguments in path").emit();
}
path
});
@ -325,24 +325,23 @@ impl<'a> Parser<'a> {
// Make a span over ${unmatched angle bracket count} characters.
let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
self.diagnostic()
.struct_span_err(
span,
&format!(
"unmatched angle bracket{}",
pluralize!(snapshot.unmatched_angle_bracket_count)
),
)
.span_suggestion(
span,
&format!(
"remove extra angle bracket{}",
pluralize!(snapshot.unmatched_angle_bracket_count)
),
String::new(),
Applicability::MachineApplicable,
)
.emit();
self.struct_span_err(
span,
&format!(
"unmatched angle bracket{}",
pluralize!(snapshot.unmatched_angle_bracket_count)
),
)
.span_suggestion(
span,
&format!(
"remove extra angle bracket{}",
pluralize!(snapshot.unmatched_angle_bracket_count)
),
String::new(),
Applicability::MachineApplicable,
)
.emit();
// Try again without unmatched angle bracket characters.
self.parse_generic_args()
@ -407,9 +406,11 @@ impl<'a> Parser<'a> {
if self.token.is_bool_lit() {
self.parse_literal_maybe_minus()?
} else {
return Err(
self.fatal("identifiers may currently not be used for const generics")
);
let span = self.token.span;
let msg = "identifiers may currently not be used for const generics";
self.struct_span_err(span, msg).emit();
let block = self.mk_block_err(span);
self.mk_expr(span, ast::ExprKind::Block(block, None), ast::AttrVec::new())
}
} else {
self.parse_literal_maybe_minus()?

View File

@ -193,7 +193,8 @@ impl<'a> Parser<'a> {
if self.prev_token_kind == PrevTokenKind::DocComment {
self.span_fatal_err(self.prev_span, Error::UselessDocComment).emit();
} else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
self.span_err(self.token.span, "expected statement after outer attribute");
self.struct_span_err(self.token.span, "expected statement after outer attribute")
.emit();
}
}
}
@ -324,7 +325,7 @@ impl<'a> Parser<'a> {
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
let sp = self.token.span;
let tok = super::token_descr(&self.token);
let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
let mut e = self.struct_span_err(sp, &format!("expected `{{`, found {}", tok));
let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
// Check to see if the user has written something like
@ -397,10 +398,7 @@ impl<'a> Parser<'a> {
self.maybe_annotate_with_ascription(&mut err, false);
err.emit();
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
Some(self.mk_stmt(
self.token.span,
StmtKind::Expr(self.mk_expr_err(self.token.span)),
))
Some(self.mk_stmt_err(self.token.span))
}
Ok(stmt) => stmt,
};
@ -478,4 +476,12 @@ impl<'a> Parser<'a> {
pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
Stmt { id: DUMMY_NODE_ID, kind, span }
}
fn mk_stmt_err(&self, span: Span) -> Stmt {
self.mk_stmt(span, StmtKind::Expr(self.mk_expr_err(span)))
}
pub(super) fn mk_block_err(&self, span: Span) -> P<Block> {
self.mk_block(vec![self.mk_stmt_err(span)], BlockCheckMode::Default, span)
}
}

View File

@ -175,7 +175,9 @@ impl<'a> Parser<'a> {
{
let path = match bounds.remove(0) {
GenericBound::Trait(pt, ..) => pt.trait_ref.path,
GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
GenericBound::Outlives(..) => {
self.span_bug(ty.span, "unexpected lifetime bound")
}
};
self.parse_remaining_bounds(Vec::new(), path, lo, true)
}

View File

@ -15,10 +15,11 @@ bitflags = "1.2.1"
log = "0.4"
syntax = { path = "../libsyntax" }
rustc_expand = { path = "../librustc_expand" }
rustc = { path = "../librustc" }
arena = { path = "../libarena" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
syntax_pos = { path = "../librustc_span", package = "rustc_span" }
rustc = { path = "../librustc" }
rustc_ast_lowering = { path = "../librustc_ast_lowering" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
rustc_metadata = { path = "../librustc_metadata" }

View File

@ -24,7 +24,7 @@ use rustc::hir::def::Namespace::*;
use rustc::hir::def::{self, CtorKind, CtorOf, DefKind, ExportMap, NonMacroAttrKind, PartialRes};
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::map::Definitions;
use rustc::hir::{self, Bool, Char, Float, Int, PrimTy, Str, Uint};
use rustc::hir::{Bool, Char, Float, Int, PrimTy, Str, Uint};
use rustc::hir::{GlobMap, TraitMap};
use rustc::lint;
use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
@ -1028,7 +1028,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
/// the resolver is no longer needed as all the relevant information is inline.
impl<'a> hir::lowering::Resolver for Resolver<'a> {
impl rustc_ast_lowering::Resolver for Resolver<'_> {
fn cstore(&self) -> &dyn CrateStore {
self.cstore()
}

View File

@ -11,7 +11,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_match(
&self,
expr: &'tcx hir::Expr<'tcx>,
discrim: &'tcx hir::Expr<'tcx>,
scrut: &'tcx hir::Expr<'tcx>,
arms: &'tcx [hir::Arm<'tcx>],
expected: Expectation<'tcx>,
match_src: hir::MatchSource,
@ -27,7 +27,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Type check the descriminant and get its type.
let discrim_ty = if force_scrutinee_bool {
let scrut_ty = if force_scrutinee_bool {
// Here we want to ensure:
//
// 1. That default match bindings are *not* accepted in the condition of an
@ -36,9 +36,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
//
// FIXME(60707): Consider removing hack with principled solution.
self.check_expr_has_type_or_error(discrim, self.tcx.types.bool, |_| {})
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
} else {
self.demand_discriminant_type(arms, discrim)
self.demand_scrutinee_type(arms, scrut)
};
// If there are no arms, that is a diverging match; a special case.
@ -51,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Otherwise, we have to union together the types that the
// arms produce and so forth.
let discrim_diverges = self.diverges.get();
let scrut_diverges = self.diverges.get();
self.diverges.set(Diverges::Maybe);
// rust-lang/rust#55810: Typecheck patterns first (via eager
@ -61,7 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.map(|arm| {
let mut all_pats_diverge = Diverges::WarnedAlways;
self.diverges.set(Diverges::Maybe);
self.check_pat_top(&arm.pat, discrim_ty, Some(discrim.span));
self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true);
all_pats_diverge &= self.diverges.get();
// As discussed with @eddyb, this is for disabling unreachable_code
@ -157,7 +157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source: match_src,
prior_arms: other_arms.clone(),
last_ty: prior_arm_ty.unwrap(),
discrim_hir_id: discrim.hir_id,
scrut_hir_id: scrut.hir_id,
}),
),
};
@ -186,8 +186,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
}
// We won't diverge unless the discriminant or all arms diverge.
self.diverges.set(discrim_diverges | all_arms_diverge);
// We won't diverge unless the scrutinee or all arms diverge.
self.diverges.set(scrut_diverges | all_arms_diverge);
coercion.complete(self)
}
@ -388,14 +388,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
}
fn demand_discriminant_type(
fn demand_scrutinee_type(
&self,
arms: &'tcx [hir::Arm<'tcx>],
discrim: &'tcx hir::Expr<'tcx>,
scrut: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
// Not entirely obvious: if matches may create ref bindings, we want to
// use the *precise* type of the discriminant, *not* some supertype, as
// the "discriminant type" (issue #23116).
// use the *precise* type of the scrutinee, *not* some supertype, as
// the "scrutinee type" (issue #23116).
//
// arielb1 [writes here in this comment thread][c] that there
// is certainly *some* potential danger, e.g., for an example
@ -454,17 +454,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
if let Some(m) = contains_ref_bindings {
self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
} else {
// ...but otherwise we want to use any supertype of the
// discriminant. This is sort of a workaround, see note (*) in
// scrutinee. This is sort of a workaround, see note (*) in
// `check_pat` for some details.
let discrim_ty = self.next_ty_var(TypeVariableOrigin {
let scrut_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: discrim.span,
span: scrut.span,
});
self.check_expr_has_type_or_error(discrim, discrim_ty, |_| {});
discrim_ty
self.check_expr_has_type_or_error(scrut, scrut_ty, |_| {});
scrut_ty
}
}
}

View File

@ -1,13 +1,13 @@
use crate::check::FnCtxt;
use rustc::infer::InferOk;
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use rustc::traits::{self, ObligationCause};
use errors::{Applicability, DiagnosticBuilder};
use rustc::hir::{self, is_range_literal, print, Node};
use rustc::ty::adjustment::AllowTwoPhase;
use rustc::ty::{self, AssocItem, Ty};
use syntax::symbol::sym;
use syntax::util::parser::PREC_POSTFIX;
use syntax_pos::symbol::sym;
use syntax_pos::Span;
use super::method::probe;
@ -79,35 +79,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
pub fn demand_eqtype_pat_diag(
&self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
match_expr_span: Option<Span>,
) -> Option<DiagnosticBuilder<'tcx>> {
let cause = if let Some(span) = match_expr_span {
self.cause(
cause_span,
ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected },
)
} else {
self.misc(cause_span)
};
self.demand_eqtype_with_origin(&cause, expected, actual)
}
pub fn demand_eqtype_pat(
&self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
match_expr_span: Option<Span>,
) {
self.demand_eqtype_pat_diag(cause_span, expected, actual, match_expr_span)
.map(|mut err| err.emit());
}
pub fn demand_coerce(
&self,
expr: &hir::Expr<'_>,

View File

@ -1268,13 +1268,17 @@ fn check_fn<'a, 'tcx>(
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
let tcx = fcx.tcx;
let sess = tcx.sess;
let hir = tcx.hir();
let declared_ret_ty = fn_sig.output();
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
let revealed_ret_ty =
fcx.instantiate_opaque_types_from_value(fn_id, &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)));
fn_sig = fcx.tcx.mk_fn_sig(
fn_sig = tcx.mk_fn_sig(
fn_sig.inputs().iter().cloned(),
revealed_ret_ty,
fn_sig.c_variadic,
@ -1284,7 +1288,7 @@ fn check_fn<'a, 'tcx>(
let span = body.value.span;
fn_maybe_err(fcx.tcx, span, fn_sig.abi);
fn_maybe_err(tcx, span, fn_sig.abi);
if body.generator_kind.is_some() && can_be_generator.is_some() {
let yield_ty = fcx
@ -1293,37 +1297,39 @@ fn check_fn<'a, 'tcx>(
fcx.yield_ty = Some(yield_ty);
}
let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir().local_def_id(fn_id));
let outer_hir_id = fcx.tcx.hir().as_local_hir_id(outer_def_id).unwrap();
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id));
let outer_hir_id = hir.as_local_hir_id(outer_def_id).unwrap();
GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// (as it's created inside the body itself, not passed in from outside).
let maybe_va_list = if fn_sig.c_variadic {
let va_list_did = fcx.tcx.require_lang_item(
let va_list_did = tcx.require_lang_item(
lang_items::VaListTypeLangItem,
Some(body.params.last().unwrap().span),
);
let region = fcx.tcx.mk_region(ty::ReScope(region::Scope {
let region = tcx.mk_region(ty::ReScope(region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite,
}));
Some(fcx.tcx.type_of(va_list_did).subst(fcx.tcx, &[region.into()]))
Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
} else {
None
};
// Add formal parameters.
for (param_ty, param) in fn_sig.inputs().iter().copied().chain(maybe_va_list).zip(body.params) {
let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
let inputs_fn = fn_sig.inputs().iter().copied();
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
// Check the pattern.
fcx.check_pat_top(&param.pat, param_ty, None);
fcx.check_pat_top(&param.pat, param_ty, try { inputs_hir?.get(idx)?.span }, false);
// Check that argument is Sized.
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
// for simple cases like `fn foo(x: Trait)`,
// where we would error once on the parameter as a whole, and once on the binding `x`.
if param.pat.simple_ident().is_none() && !fcx.tcx.features().unsized_locals {
if param.pat.simple_ident().is_none() && !tcx.features().unsized_locals {
fcx.require_type_is_sized(param_ty, decl.output.span(), traits::SizedArgumentType);
}
@ -1384,11 +1390,11 @@ fn check_fn<'a, 'tcx>(
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
// Check that the main return type implements the termination trait.
if let Some(term_id) = fcx.tcx.lang_items().termination() {
if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) {
let main_id = fcx.tcx.hir().as_local_hir_id(def_id).unwrap();
if let Some(term_id) = tcx.lang_items().termination() {
if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) {
let main_id = hir.as_local_hir_id(def_id).unwrap();
if main_id == fn_id {
let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
let substs = tcx.mk_substs_trait(declared_ret_ty, &[]);
let trait_ref = ty::TraitRef::new(term_id, substs);
let return_ty_span = decl.output.span();
let cause = traits::ObligationCause::new(
@ -1407,15 +1413,15 @@ fn check_fn<'a, 'tcx>(
}
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
if panic_impl_did == fcx.tcx.hir().local_def_id(fn_id) {
if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
if let Some(panic_impl_did) = tcx.lang_items().panic_impl() {
if panic_impl_did == hir.local_def_id(fn_id) {
if let Some(panic_info_did) = tcx.lang_items().panic_info() {
if declared_ret_ty.kind != ty::Never {
fcx.tcx.sess.span_err(decl.output.span(), "return type should be `!`");
sess.span_err(decl.output.span(), "return type should be `!`");
}
let inputs = fn_sig.inputs();
let span = fcx.tcx.hir().span(fn_id);
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_panic_info = match inputs[0].kind {
ty::Ref(region, ty, mutbl) => match ty.kind {
@ -1430,38 +1436,36 @@ fn check_fn<'a, 'tcx>(
};
if !arg_is_panic_info {
fcx.tcx
.sess
.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
}
if let Node::Item(item) = fcx.tcx.hir().get(fn_id) {
if let Node::Item(item) = hir.get(fn_id) {
if let ItemKind::Fn(_, ref generics, _) = item.kind {
if !generics.params.is_empty() {
fcx.tcx.sess.span_err(span, "should have no type parameters");
sess.span_err(span, "should have no type parameters");
}
}
}
} else {
let span = fcx.tcx.sess.source_map().def_span(span);
fcx.tcx.sess.span_err(span, "function should have one argument");
let span = sess.source_map().def_span(span);
sess.span_err(span, "function should have one argument");
}
} else {
fcx.tcx.sess.err("language item required, but not found: `panic_info`");
sess.err("language item required, but not found: `panic_info`");
}
}
}
// Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() {
if alloc_error_handler_did == fcx.tcx.hir().local_def_id(fn_id) {
if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() {
if let Some(alloc_error_handler_did) = tcx.lang_items().oom() {
if alloc_error_handler_did == hir.local_def_id(fn_id) {
if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() {
if declared_ret_ty.kind != ty::Never {
fcx.tcx.sess.span_err(decl.output.span(), "return type should be `!`");
sess.span_err(decl.output.span(), "return type should be `!`");
}
let inputs = fn_sig.inputs();
let span = fcx.tcx.hir().span(fn_id);
let span = hir.span(fn_id);
if inputs.len() == 1 {
let arg_is_alloc_layout = match inputs[0].kind {
ty::Adt(ref adt, _) => adt.did == alloc_layout_did,
@ -1469,13 +1473,13 @@ fn check_fn<'a, 'tcx>(
};
if !arg_is_alloc_layout {
fcx.tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
}
if let Node::Item(item) = fcx.tcx.hir().get(fn_id) {
if let Node::Item(item) = hir.get(fn_id) {
if let ItemKind::Fn(_, ref generics, _) = item.kind {
if !generics.params.is_empty() {
fcx.tcx.sess.span_err(
sess.span_err(
span,
"`#[alloc_error_handler]` function should have no type \
parameters",
@ -1484,11 +1488,11 @@ fn check_fn<'a, 'tcx>(
}
}
} else {
let span = fcx.tcx.sess.source_map().def_span(span);
fcx.tcx.sess.span_err(span, "function should have one argument");
let span = sess.source_map().def_span(span);
sess.span_err(span, "function should have one argument");
}
} else {
fcx.tcx.sess.err("language item required, but not found: `alloc_layout`");
sess.err("language item required, but not found: `alloc_layout`");
}
}
}
@ -4304,18 +4308,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
/// Type check a `let` statement.
pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
let t = self.local_ty(local.span, local.hir_id).decl_ty;
self.write_ty(local.hir_id, t);
// Determine and write the type which we'll check the pattern against.
let ty = self.local_ty(local.span, local.hir_id).decl_ty;
self.write_ty(local.hir_id, ty);
// Type check the initializer.
if let Some(ref init) = local.init {
let init_ty = self.check_decl_initializer(local, &init);
self.overwrite_local_ty_if_err(local, t, init_ty);
self.overwrite_local_ty_if_err(local, ty, init_ty);
}
self.check_pat_top(&local.pat, t, None);
// Does the expected pattern type originate from an expression and what is the span?
let (origin_expr, ty_span) = match (local.ty, local.init) {
(Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
(_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee.
_ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
};
// Type check the pattern. Override if necessary to avoid knock-on errors.
self.check_pat_top(&local.pat, ty, ty_span, origin_expr);
let pat_ty = self.node_ty(local.pat.hir_id);
self.overwrite_local_ty_if_err(local, t, pat_ty);
self.overwrite_local_ty_if_err(local, ty, pat_ty);
}
fn overwrite_local_ty_if_err(
@ -4325,7 +4340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
) {
if ty.references_error() {
// Override the types everywhere with `types.err` to avoid knock down errors.
// Override the types everywhere with `types.err` to avoid knock on errors.
self.write_ty(local.hir_id, ty);
self.write_ty(local.pat.hir_id, ty);
let local_ty = LocalTy { decl_ty, revealed_ty: ty };

View File

@ -6,6 +6,7 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use rustc::hir::{self, HirId, Pat, PatKind};
use rustc::infer;
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::traits::Pattern;
use rustc::ty::subst::GenericArg;
use rustc::ty::{self, BindingMode, Ty, TypeFoldable};
use syntax::ast;
@ -29,39 +30,97 @@ pointers. If you encounter this error you should try to avoid dereferencing the
You can read more about trait objects in the Trait Objects section of the Reference: \
https://doc.rust-lang.org/reference/types.html#trait-objects";
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_pat_top(
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
discrim_span: Option<Span>,
) {
let def_bm = BindingMode::BindByValue(hir::Mutability::Not);
self.check_pat(pat, expected, def_bm, discrim_span);
}
/// `discrim_span` argument having a `Span` indicates that this pattern is part of a match
/// expression arm guard, and it points to the match discriminant to add context in type errors.
/// In the following example, `discrim_span` corresponds to the `a + b` expression:
/// Information about the expected type at the top level of type checking a pattern.
///
/// **NOTE:** This is only for use by diagnostics. Do NOT use for type checking logic!
#[derive(Copy, Clone)]
struct TopInfo<'tcx> {
/// The `expected` type at the top level of type checking a pattern.
expected: Ty<'tcx>,
/// Was the origin of the `span` from a scrutinee expression?
///
/// Otherwise there is no scrutinee and it could be e.g. from the type of a formal parameter.
origin_expr: bool,
/// The span giving rise to the `expected` type, if one could be provided.
///
/// If `origin_expr` is `true`, then this is the span of the scrutinee as in:
///
/// - `match scrutinee { ... }`
/// - `let _ = scrutinee;`
///
/// This is used to point to add context in type errors.
/// In the following example, `span` corresponds to the `a + b` expression:
///
/// ```text
/// error[E0308]: mismatched types
/// --> src/main.rs:5:9
/// --> src/main.rs:L:C
/// |
/// 4 | let temp: usize = match a + b {
/// L | let temp: usize = match a + b {
/// | ----- this expression has type `usize`
/// 5 | Ok(num) => num,
/// L | Ok(num) => num,
/// | ^^^^^^^ expected `usize`, found enum `std::result::Result`
/// |
/// = note: expected type `usize`
/// found type `std::result::Result<_, _>`
/// ```
span: Option<Span>,
}
impl<'tcx> FnCtxt<'_, 'tcx> {
fn demand_eqtype_pat_diag(
&self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ti: TopInfo<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> {
let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
let cause = self.cause(cause_span, code);
self.demand_eqtype_with_origin(&cause, expected, actual)
}
fn demand_eqtype_pat(
&self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ti: TopInfo<'tcx>,
) {
self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map(|mut err| err.emit());
}
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type check the given top level pattern against the `expected` type.
///
/// If a `Some(span)` is provided and `origin_expr` holds,
/// then the `span` represents the scrutinee's span.
/// The scrutinee is found in e.g. `match scrutinee { ... }` and `let pat = scrutinee;`.
///
/// Otherwise, `Some(span)` represents the span of a type expression
/// which originated the `expected` type.
pub fn check_pat_top(
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
span: Option<Span>,
origin_expr: bool,
) {
let def_bm = BindingMode::BindByValue(hir::Mutability::Not);
self.check_pat(pat, expected, def_bm, TopInfo { expected, origin_expr, span });
}
/// Type check the given `pat` against the `expected` type
/// with the provided `def_bm` (default binding mode).
///
/// Outside of this module, `check_pat_top` should always be used.
/// Conversely, inside this module, `check_pat_top` should never be used.
fn check_pat(
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) {
debug!("check_pat(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
@ -72,60 +131,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let is_nrp = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res));
let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, is_nrp);
let ty = match &pat.kind {
let ty = match pat.kind {
PatKind::Wild => expected,
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, discrim_span),
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
PatKind::Range(begin, end, _) => {
match self.check_pat_range(pat.span, begin, end, expected, discrim_span) {
match self.check_pat_range(pat.span, begin, end, expected, ti) {
None => return,
Some(ty) => ty,
}
}
PatKind::Binding(ba, var_id, _, sub) => {
let sub = sub.as_deref();
self.check_pat_ident(pat, *ba, *var_id, sub, expected, def_bm, discrim_span)
self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti)
}
PatKind::TupleStruct(qpath, subpats, ddpos) => self.check_pat_tuple_struct(
pat,
qpath,
subpats,
*ddpos,
expected,
def_bm,
discrim_span,
),
PatKind::Path(qpath) => {
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
}
PatKind::Path(ref qpath) => {
self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected)
}
PatKind::Struct(qpath, fields, etc) => {
self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span)
PatKind::Struct(ref qpath, fields, etc) => {
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti)
}
PatKind::Or(pats) => {
for pat in *pats {
self.check_pat(pat, expected, def_bm, discrim_span);
for pat in pats {
self.check_pat(pat, expected, def_bm, ti);
}
expected
}
PatKind::Tuple(elements, ddpos) => {
self.check_pat_tuple(pat.span, *elements, *ddpos, expected, def_bm, discrim_span)
}
PatKind::Box(inner) => {
self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span)
self.check_pat_tuple(pat.span, elements, ddpos, expected, def_bm, ti)
}
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, def_bm, ti),
PatKind::Ref(inner, mutbl) => {
self.check_pat_ref(pat, inner, *mutbl, expected, def_bm, discrim_span)
self.check_pat_ref(pat, inner, mutbl, expected, def_bm, ti)
}
PatKind::Slice(before, slice, after) => {
let slice = slice.as_deref();
self.check_pat_slice(
pat.span,
*before,
slice,
*after,
expected,
def_bm,
discrim_span,
)
self.check_pat_slice(pat.span, before, slice, after, expected, def_bm, ti)
}
};
@ -302,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
lt: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
// We've already computed the type above (when checking for a non-ref pat),
// so avoid computing it again.
@ -336,7 +377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// then that's equivalent to there existing a LUB.
if let Some(mut err) = self.demand_suptype_diag(span, expected, pat_ty) {
err.emit_unless(
discrim_span
ti.span
.filter(|&s| {
// In the case of `if`- and `while`-expressions we've already checked
// that `scrutinee: bool`. We know that the pattern is `true`,
@ -356,7 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lhs: &'tcx hir::Expr<'tcx>,
rhs: &'tcx hir::Expr<'tcx>,
expected: Ty<'tcx>,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Option<Ty<'tcx>> {
let lhs_ty = self.check_expr(lhs);
let rhs_ty = self.check_expr(rhs);
@ -377,7 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Subtyping doesn't matter here, as the value is some kind of scalar.
let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
self.demand_eqtype_pat_diag(x_span, expected, x_ty, discrim_span).map(|mut err| {
self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
self.endpoint_has_type(&mut err, y_span, y_ty);
err.emit();
});
@ -451,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sub: Option<&'tcx Pat<'tcx>>,
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
// Determine the binding mode...
let bm = match ba {
@ -481,17 +522,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected
}
};
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, discrim_span);
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
// If there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be.
if var_id != pat.hir_id {
let vt = self.local_ty(pat.span, var_id).decl_ty;
self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
self.demand_eqtype_pat(pat.span, vt, local_ty, ti);
}
if let Some(p) = sub {
self.check_pat(&p, expected, def_bm, discrim_span);
self.check_pat(&p, expected, def_bm, ti);
}
local_ty
@ -570,7 +611,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
etc: bool,
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
// Resolve the path and check the definition for errors.
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
@ -578,16 +619,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant_ty
} else {
for field in fields {
self.check_pat(&field.pat, self.tcx.types.err, def_bm, discrim_span);
self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti);
}
return self.tcx.types.err;
};
// Type-check the path.
self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
self.demand_eqtype_pat(pat.span, expected, pat_ty, ti);
// Type-check subpatterns.
if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
if self
.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm, ti)
{
pat_ty
} else {
@ -638,12 +680,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ddpos: Option<usize>,
expected: Ty<'tcx>,
def_bm: BindingMode,
match_arm_pat_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let on_error = || {
for pat in subpats {
self.check_pat(&pat, tcx.types.err, def_bm, match_arm_pat_span);
self.check_pat(&pat, tcx.types.err, def_bm, ti);
}
};
let report_unexpected_res = |res: Res| {
@ -704,7 +746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
// Type-check the tuple struct pattern against the expected type.
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, match_arm_pat_span);
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
let had_err = diag.is_some();
diag.map(|mut err| err.emit());
@ -718,7 +760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
self.check_pat(&subpat, field_ty, def_bm, match_arm_pat_span);
self.check_pat(&subpat, field_ty, def_bm, ti);
self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
}
@ -822,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ddpos: Option<usize>,
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let mut expected_len = elements.len();
@ -849,12 +891,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// further errors being emitted when using the bindings. #50333
let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat(elem, &tcx.types.err, def_bm, discrim_span);
self.check_pat(elem, &tcx.types.err, def_bm, ti);
}
tcx.mk_tup(element_tys_iter)
} else {
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat(elem, &element_tys[i].expect_ty(), def_bm, discrim_span);
self.check_pat(elem, &element_tys[i].expect_ty(), def_bm, ti);
}
pat_ty
}
@ -869,6 +911,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fields: &'tcx [hir::FieldPat<'tcx>],
etc: bool,
def_bm: BindingMode,
ti: TopInfo<'tcx>,
) -> bool {
let tcx = self.tcx;
@ -918,7 +961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
self.check_pat(&field.pat, field_ty, def_bm, None);
self.check_pat(&field.pat, field_ty, def_bm, ti);
}
let mut unmentioned_fields = variant
@ -1095,7 +1138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
inner: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, &inner) {
@ -1106,12 +1149,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: inner.span,
});
let box_ty = tcx.mk_box(inner_ty);
self.demand_eqtype_pat(span, expected, box_ty, discrim_span);
self.demand_eqtype_pat(span, expected, box_ty, ti);
(box_ty, inner_ty)
} else {
(tcx.types.err, tcx.types.err)
};
self.check_pat(&inner, inner_ty, def_bm, discrim_span);
self.check_pat(&inner, inner_ty, def_bm, ti);
box_ty
}
@ -1122,7 +1165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mutbl: hir::Mutability,
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let expected = self.shallow_resolve(expected);
@ -1157,7 +1200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
(tcx.types.err, tcx.types.err)
};
self.check_pat(&inner, inner_ty, def_bm, discrim_span);
self.check_pat(&inner, inner_ty, def_bm, ti);
rptr_ty
}
@ -1186,7 +1229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
after: &'tcx [&'tcx Pat<'tcx>],
expected: Ty<'tcx>,
def_bm: BindingMode,
discrim_span: Option<Span>,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let err = self.tcx.types.err;
let expected = self.structurally_resolved_type(span, expected);
@ -1211,15 +1254,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type check all the patterns before `slice`.
for elt in before {
self.check_pat(&elt, inner_ty, def_bm, discrim_span);
self.check_pat(&elt, inner_ty, def_bm, ti);
}
// Type check the `slice`, if present, against its expected type.
if let Some(slice) = slice {
self.check_pat(&slice, slice_ty, def_bm, discrim_span);
self.check_pat(&slice, slice_ty, def_bm, ti);
}
// Type check the elements after `slice`, if present.
for elt in after {
self.check_pat(&elt, inner_ty, def_bm, discrim_span);
self.check_pat(&elt, inner_ty, def_bm, ti);
}
expected
}

View File

@ -65,6 +65,7 @@ This API is completely unstable and subject to change.
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(slice_patterns)]
#![feature(try_blocks)]
#![feature(never_type)]
#![recursion_limit = "256"]

View File

@ -1,7 +1,7 @@
//
// min-llvm-version 8.0
// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y
#![crate_type="lib"]
// CHECK: attributes #{{.*}} "no-frame-pointer-elim"="true"
// CHECK: attributes #{{.*}} "frame-pointer"="all"
pub fn foo() {}

View File

@ -1,7 +1,8 @@
// min-llvm-version 8.0
// ignore-tidy-linelength
// compile-flags: -Z instrument-mcount
#![crate_type = "lib"]
// CHECK: attributes #{{.*}} "instrument-function-entry-inlined"="{{.*}}mcount{{.*}}" "no-frame-pointer-elim"="true"
// CHECK: attributes #{{.*}} "frame-pointer"="all" "instrument-function-entry-inlined"="{{.*}}mcount{{.*}}"
pub fn foo() {}

View File

@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13624.rs:20:9
|
LL | match enum_struct_variant {
| ------------------- this match expression has type `()`
| ------------------- this expression has type `()`
LL | a::Enum::EnumStructVariant { x, y, z } => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `a::Enum`

View File

@ -44,7 +44,9 @@ error[E0308]: mismatched types
--> $DIR/destructure-trait-ref.rs:42:13
|
LL | let box box x = box 1isize as Box<dyn T>;
| ^^^^^ expected trait `T`, found struct `std::boxed::Box`
| ^^^^^ ------------------------ this expression has type `std::boxed::Box<dyn T>`
| |
| expected trait `T`, found struct `std::boxed::Box`
|
= note: expected trait object `dyn T`
found struct `std::boxed::Box<_>`

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/E0308-4.rs:4:15
|
LL | match x {
| - this match expression has type `u8`
| - this expression has type `u8`
LL | 0u8..=3i8 => (),
| --- ^^^ expected `u8`, found `i8`
| |

View File

@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99.., _] => {},
| ^^ expected struct `std::ops::Range`, found integer
|

View File

@ -14,7 +14,7 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99..] => {},
| ^^ expected struct `std::ops::Range`, found integer
|

View File

@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
| ^ expected struct `std::ops::Range`, found integer
|
@ -19,7 +19,7 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
| ^^ --- this is of type `{integer}`
| |
@ -32,7 +32,7 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
| -- ^^^ expected struct `std::ops::Range`, found integer
| |

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-11844.rs:6:9
|
LL | match a {
| - this match expression has type `std::option::Option<std::boxed::Box<{integer}>>`
| - this expression has type `std::option::Option<std::boxed::Box<{integer}>>`
LL | Ok(a) =>
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-12552.rs:6:5
|
LL | match t {
| - this match expression has type `std::result::Result<_, {integer}>`
| - this expression has type `std::result::Result<_, {integer}>`
LL | Some(k) => match k {
| ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
|

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13466.rs:8:9
|
LL | let _x: usize = match Some(1) {
| ------- this match expression has type `std::option::Option<{integer}>`
| ------- this expression has type `std::option::Option<{integer}>`
LL | Ok(u) => u,
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13466.rs:14:9
|
LL | let _x: usize = match Some(1) {
| ------- this match expression has type `std::option::Option<{integer}>`
| ------- this expression has type `std::option::Option<{integer}>`
...
LL | Err(e) => panic!(e)
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`

View File

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/issue-14541.rs:5:9
|
LL | let Vec3 { y: _, z: _ } = v;
| ^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found struct `Vec3`
| ^^^^^^^^^^^^^^^^^^^ - this expression has type `Vec2`
| |
| expected struct `Vec2`, found struct `Vec3`
error: aborting due to previous error

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-15896.rs:11:11
|
LL | let u = match e {
| - this match expression has type `main::R`
| - this expression has type `main::E`
LL | E::B(
LL | Tau{t: x},
| ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`

View File

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/issue-16338.rs:7:9
|
LL | let Slice { data: data, len: len } = "foo";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `str`, found struct `Slice`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----- this expression has type `&str`
| |
| expected `str`, found struct `Slice`
|
= note: expected type `str`
found struct `Slice<_>`

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-16401.rs:8:9
|
LL | match () {
| -- this match expression has type `()`
| -- this expression has type `()`
LL | Slice { data: data, len: len } => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Slice`
|

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-3680.rs:3:9
|
LL | match None {
| ---- this match expression has type `std::option::Option<_>`
| ---- this expression has type `std::option::Option<_>`
LL | Err(_) => ()
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|

View File

@ -8,7 +8,9 @@ error[E0308]: mismatched types
--> $DIR/issue-37026.rs:7:9
|
LL | let empty_struct::XEmpty6(..) = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `empty_struct::XEmpty6`
| ^^^^^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()`
| |
| expected `()`, found struct `empty_struct::XEmpty6`
error: aborting due to 2 previous errors

View File

@ -29,7 +29,7 @@ error[E0308]: mismatched types
--> $DIR/issue-5100.rs:33:9
|
LL | match (true, false) {
| ------------- this match expression has type `(bool, bool)`
| ------------- this expression has type `(bool, bool)`
LL | box (true, false) => ()
| ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
|

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-5358-1.rs:6:9
|
LL | match S(Either::Left(5)) {
| ------------------ this match expression has type `S`
| ------------------ this expression has type `S`
LL | Either::Right(_) => {}
| ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
|

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-57741-1.rs:14:9
|
LL | let y = match x {
| - this match expression has type `std::boxed::Box<u32>`
| - this expression has type `std::boxed::Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/issue-57741-1.rs:14:22
|
LL | let y = match x {
| - this match expression has type `std::boxed::Box<u32>`
| - this expression has type `std::boxed::Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|

View File

@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<T>`
| this expression has type `std::boxed::Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
@ -18,7 +18,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<T>`
| this expression has type `std::boxed::Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
@ -32,7 +32,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<S>`
| this expression has type `std::boxed::Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
@ -46,7 +46,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<S>`
| this expression has type `std::boxed::Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`

View File

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
|
LL | let P() = U {};
| ^^^ expected struct `U`, found struct `P`
| ^^^ ---- this expression has type `U`
| |
| expected struct `U`, found struct `P`
|
= note: expected struct `U`
found struct `P<_>`

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-7092.rs:6:9
|
LL | match x {
| - this match expression has type `Whatever`
| - this expression has type `Whatever`
LL | Some(field) =>
| ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
|

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/match-struct.rs:6:9
|
LL | match (S { a: 1 }) {
| ------------ this match expression has type `S`
| ------------ this expression has type `S`
LL | E::C(_) => (),
| ^^^^^^^ expected struct `S`, found enum `E`

View File

@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } }
| - ^^^^^^^ expected enum `A`, found enum `B`
| |
| this match expression has type `A`
| this expression has type `A`
error: aborting due to previous error

View File

@ -9,6 +9,8 @@ LL | (0, ref y) | (y, 0) => {}
error[E0308]: mismatched types
--> $DIR/E0409.rs:5:23
|
LL | match x {
| - this expression has type `({integer}, {integer})`
LL | (0, ref y) | (y, 0) => {}
| ^ expected `&{integer}`, found integer

View File

@ -94,7 +94,9 @@ error[E0308]: mismatched types
--> $DIR/already-bound-name.rs:33:31
|
LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
| ^ expected integer, found enum `E`
| ^ ------- this expression has type `E<E<{integer}>>`
| |
| expected integer, found enum `E`
|
= note: expected type `{integer}`
found type `E<{integer}>`

View File

@ -60,7 +60,9 @@ error[E0308]: mismatched types
--> $DIR/inconsistent-modes.rs:13:25
|
LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
| ^^^^^^^^^ types differ in mutability
| ^^^^^^^^^ -------------------- expected due to this
| |
| types differ in mutability
|
= note: expected type `&&u8`
found type `&mut &mut u8`
@ -69,7 +71,9 @@ error[E0308]: mismatched types
--> $DIR/inconsistent-modes.rs:16:31
|
LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
| ^^^^^^^^^ types differ in mutability
| ^^^^^^^^^ ----------- this expression has type `std::result::Result<({integer}, &{integer}), (_, _)>`
| |
| types differ in mutability
|
= note: expected type `&{integer}`
found type `&mut _`

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/or-pattern-mismatch.rs:3:68
|
LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } }
| ^ expected `usize`, found `isize`
| ---------------- this expression has type `Blah` ^ expected `usize`, found `isize`
error: aborting due to previous error

View File

@ -112,3 +112,4 @@ fn main() {}
#[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
//~^ ERROR expected statement after outer attribute
#[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
//~^ ERROR expected statement after outer attribute

View File

@ -410,5 +410,11 @@ error: expected statement after outer attribute
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
| ^
error: aborting due to 56 previous errors
error: expected statement after outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:114:45
|
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
| ^
error: aborting due to 57 previous errors

View File

@ -2,7 +2,9 @@ error: unexpected `{` after qualified path
--> $DIR/brace-after-qualified-path-in-match.rs:3:27
|
LL | <T as Trait>::Type{key: value} => (),
| ^ unexpected `{` after qualified path
| ------------------^ unexpected `{` after qualified path
| |
| the qualified path
error: aborting due to previous error

View File

@ -2,7 +2,9 @@ error: unexpected `(` after qualified path
--> $DIR/paren-after-qualified-path-in-match.rs:3:27
|
LL | <T as Trait>::Type(2) => (),
| ^ unexpected `(` after qualified path
| ------------------^ unexpected `(` after qualified path
| |
| the qualified path
error: aborting due to previous error

View File

@ -17,7 +17,7 @@ error[E0308]: mismatched types
--> $DIR/pat-tuple-5.rs:5:10
|
LL | match (0, 1) {
| ------ this match expression has type `({integer}, {integer})`
| ------ this expression has type `({integer}, {integer})`
LL | (PAT ..) => {}
| ^^^ expected tuple, found `u8`
|

View File

@ -425,8 +425,9 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:23:16
|
LL | if let X.. .0 = 0 {}
| - ^^ expected integer, found floating-point number
| |
| - ^^ - this expression has type `u8`
| | |
| | expected integer, found floating-point number
| this is of type `u8`
error[E0029]: only char and numeric types are allowed in range patterns
@ -457,8 +458,9 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:36:16
|
LL | if let X..=.0 = 0 {}
| - ^^ expected integer, found floating-point number
| |
| - ^^ - this expression has type `u8`
| | |
| | expected integer, found floating-point number
| this is of type `u8`
error[E0029]: only char and numeric types are allowed in range patterns
@ -489,8 +491,9 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:52:17
|
LL | if let X... .0 = 0 {}
| - ^^ expected integer, found floating-point number
| |
| - ^^ - this expression has type `u8`
| | |
| | expected integer, found floating-point number
| this is of type `u8`
error[E0029]: only char and numeric types are allowed in range patterns

View File

@ -0,0 +1,9 @@
struct S {
f: u8,
}
fn main() {
match (S { f: 42 }) {
S { f: Ok(_) } => {} //~ ERROR mismatched types
}
}

View File

@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/pat-struct-field-expr-has-type.rs:7:16
|
LL | match (S { f: 42 }) {
| ------------- this expression has type `S`
LL | S { f: Ok(_) } => {}
| ^^^^^ expected `u8`, found enum `std::result::Result`
|
= note: expected type `u8`
found enum `std::result::Result<_, _>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,8 @@
// Test the `.span_label(..)` to the type when there's a
// type error in a pattern due to a the formal parameter.
fn main() {}
struct Tuple(u8);
fn foo(Tuple(_): String) {} //~ ERROR mismatched types

View File

@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/pat-type-err-formal-param.rs:8:8
|
LL | fn foo(Tuple(_): String) {}
| ^^^^^^^^ ------ expected due to this
| |
| expected struct `std::string::String`, found struct `Tuple`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,16 @@
// Test the `.span_label` to the type / scrutinee
// when there's a type error in checking a pattern.
fn main() {
// We want to point at the `Option<u8>`.
let Ok(0): Option<u8> = 42u8;
//~^ ERROR mismatched types
//~| ERROR mismatched types
// We want to point at the `Option<u8>`.
let Ok(0): Option<u8>;
//~^ ERROR mismatched types
// We want to point at the scrutinee.
let Ok(0) = 42u8; //~ ERROR mismatched types
}

View File

@ -0,0 +1,49 @@
error[E0308]: mismatched types
--> $DIR/pat-type-err-let-stmt.rs:6:29
|
LL | let Ok(0): Option<u8> = 42u8;
| ---------- ^^^^
| | |
| | expected enum `std::option::Option`, found `u8`
| | help: try using a variant of the expected enum: `Some(42u8)`
| expected due to this
|
= note: expected enum `std::option::Option<u8>`
found type `u8`
error[E0308]: mismatched types
--> $DIR/pat-type-err-let-stmt.rs:6:9
|
LL | let Ok(0): Option<u8> = 42u8;
| ^^^^^ ---------- expected due to this
| |
| expected enum `std::option::Option`, found enum `std::result::Result`
|
= note: expected enum `std::option::Option<u8>`
found enum `std::result::Result<_, _>`
error[E0308]: mismatched types
--> $DIR/pat-type-err-let-stmt.rs:11:9
|
LL | let Ok(0): Option<u8>;
| ^^^^^ ---------- expected due to this
| |
| expected enum `std::option::Option`, found enum `std::result::Result`
|
= note: expected enum `std::option::Option<u8>`
found enum `std::result::Result<_, _>`
error[E0308]: mismatched types
--> $DIR/pat-type-err-let-stmt.rs:15:9
|
LL | let Ok(0) = 42u8;
| ^^^^^ ---- this expression has type `u8`
| |
| expected `u8`, found enum `std::result::Result`
|
= note: expected type `u8`
found enum `std::result::Result<_, _>`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -28,7 +28,7 @@ error[E0308]: mismatched types
--> $DIR/pattern-error-continue.rs:22:9
|
LL | match 'c' {
| --- this match expression has type `char`
| --- this expression has type `char`
LL | S { .. } => (),
| ^^^^^^^^ expected `char`, found struct `S`

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/pattern-tyvar.rs:5:18
|
LL | match t {
| - this match expression has type `std::option::Option<std::vec::Vec<isize>>`
| - this expression has type `Bar`
LL | Bar::T1(_, Some::<isize>(x)) => {
| ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found `isize`
|

View File

@ -23,18 +23,24 @@ LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-binding-mode.rs:7:32
|
LL | match x {
| - this expression has type `Opts`
LL | Opts::A(ref i) | Opts::B(i) => {}
| ^ expected `&isize`, found `isize`
error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-binding-mode.rs:16:32
|
LL | match x {
| - this expression has type `Opts`
LL | Opts::A(ref i) | Opts::B(i) => {}
| ^ expected `&isize`, found `isize`
error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-binding-mode.rs:25:36
|
LL | match x {
| - this expression has type `Opts`
LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
| ^^^^^ types differ in mutability
|

View File

@ -86,6 +86,8 @@ LL | (CONST1, _) | (_, Const2) => ()
error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-names.rs:19:19
|
LL | match x {
| - this expression has type `(E, E)`
LL | (A, B) | (ref B, c) | (c, A) => ()
| ^^^^^ expected enum `E`, found `&E`

View File

@ -630,7 +630,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:67:12
|
LL | if let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@ -650,7 +650,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:71:12
|
LL | if let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@ -697,7 +697,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:86:12
|
LL | if let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@ -818,7 +818,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:131:15
|
LL | while let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@ -838,7 +838,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:135:15
|
LL | while let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@ -885,7 +885,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:150:15
|
LL | while let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@ -961,7 +961,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:198:10
|
LL | (let Range { start: _, end: _ } = true..true || false);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|

View File

@ -86,7 +86,7 @@ error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:54:9
|
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this match expression has type `Point<{integer}>`
| ---------------------- this expression has type `Point<{integer}>`
LL | PointF::<u32> { .. } => {}
| ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
|
@ -97,7 +97,7 @@ error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:59:9
|
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this match expression has type `Point<{integer}>`
| ---------------------- this expression has type `Point<{integer}>`
LL | PointF { .. } => {}
| ^^^^^^^^^^^^^ expected integer, found `f32`
|
@ -108,7 +108,7 @@ error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:67:9
|
LL | match (Pair { x: 1, y: 2 }) {
| --------------------- this match expression has type `Pair<{integer}, {integer}>`
| --------------------- this expression has type `Pair<{integer}, {integer}>`
LL | PairF::<u32> { .. } => {}
| ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
|

View File

@ -5,11 +5,12 @@ LL | Some(vec![_x]) => (),
| ^^^^^^^^
| |
| unexpected `(` after qualified path
| the qualified path
| in this macro invocation
| help: use a slice pattern here instead: `[_x]`
|
= help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error