From 6db48380ce437bcb21da450db1696ede0fcba158 Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Tue, 13 Jun 2017 20:14:23 +0000 Subject: [PATCH 1/3] rustc_typeck: remove old-style WF obligation --- src/librustc_typeck/check/mod.rs | 34 -------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 701de029b2b..c08eeb740ec 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -992,14 +992,6 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { - // The type of the argument must be well-formed. - // - // NB -- this is now checked in wfcheck, but that - // currently only results in warnings, so we issue an - // old-style WF obligation here so that we still get the - // errors that we used to get. - fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation); - // Check the pattern. fcx.check_pat_arg(&arg.pat, arg_ty, true); fcx.write_ty(arg.id, arg_ty); @@ -1977,17 +1969,6 @@ pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { } } - /// Registers an obligation for checking later, during regionck, that the type `ty` must - /// outlive the region `r`. - pub fn register_region_obligation(&self, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - cause: traits::ObligationCause<'tcx>) - { - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); - fulfillment_cx.register_region_obligation(ty, region, cause); - } - /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. pub fn register_wf_obligation(&self, @@ -2002,21 +1983,6 @@ pub fn register_wf_obligation(&self, ty::Predicate::WellFormed(ty))); } - pub fn register_old_wf_obligation(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { - // Registers an "old-style" WF obligation that uses the - // implicator code. This is basically a buggy version of - // `register_wf_obligation` that is being kept around - // temporarily just to help with phasing in the newer rules. - // - // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually - let cause = traits::ObligationCause::new(span, self.body_id, code); - self.register_region_obligation(ty, self.tcx.types.re_empty, cause); - } - /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { From 74cb315a109f9b7a4a73cc6bf3ac481e92ec926d Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Tue, 13 Jun 2017 20:22:28 +0000 Subject: [PATCH 2/3] rustc_typeck: enforce argument type is sized --- src/librustc_typeck/check/mod.rs | 9 ++++++++ src/test/compile-fail/issue-38954.rs | 6 ++---- src/test/compile-fail/issue-42312.rs | 21 +++++++++++++++++++ .../run-pass/associated-types-sugar-path.rs | 2 -- 4 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/issue-42312.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c08eeb740ec..a0afd58e586 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -994,6 +994,15 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { // Check the pattern. fcx.check_pat_arg(&arg.pat, arg_ty, true); + + // 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 arg.pat.simple_name().is_none() { + fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation); + } + fcx.write_ty(arg.id, arg_ty); } diff --git a/src/test/compile-fail/issue-38954.rs b/src/test/compile-fail/issue-38954.rs index 65b17a3db0b..896728b6da0 100644 --- a/src/test/compile-fail/issue-38954.rs +++ b/src/test/compile-fail/issue-38954.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] - fn _test(ref _p: str) {} +//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277] -#[rustc_error] -fn main() { } //~ ERROR compilation successful +fn main() { } diff --git a/src/test/compile-fail/issue-42312.rs b/src/test/compile-fail/issue-42312.rs new file mode 100644 index 00000000000..06573b42b59 --- /dev/null +++ b/src/test/compile-fail/issue-42312.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +pub trait Foo { + fn baz(_: Self::Target) where Self: Deref {} + //~^ ERROR `::Target: std::marker::Sized` is not satisfied +} + +pub fn f(_: ToString) {} +//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied + +fn main() { } diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 587fb3f80d6..d8d42f2cba2 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -15,8 +15,6 @@ pub trait Foo { type A; fn boo(&self) -> Self::A; - - fn baz(_: Self::Target) where Self: Deref {} } impl Foo for isize { From 5ed21f5d47c28e0e1541c037683becb90adabe65 Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Wed, 28 Jun 2017 16:26:36 +0000 Subject: [PATCH 3/3] rustc_typeck: use body-id of type-checking item in need_type_info --- .../infer/error_reporting/need_type_info.rs | 12 +++++------- src/librustc/traits/error_reporting.rs | 16 +++++++++------- src/librustc/traits/mod.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 4 ++-- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/mod.rs | 7 +++++-- src/librustc_typeck/check/writeback.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- src/test/compile-fail/issue-23046.rs | 4 ++-- 11 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 7361d66428f..a684881c091 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::{self, map, Local, Pat, Body}; +use hir::{self, Local, Pat, Body}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::InferCtxt; use infer::type_variable::TypeVariableOrigin; @@ -88,7 +88,7 @@ fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { } } - pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { + pub fn need_type_info(&self, body_id: Option, span: Span, ty: Ty<'tcx>) { let ty = self.resolve_type_vars_if_possible(&ty); let name = self.extract_type_name(&ty); @@ -103,11 +103,9 @@ pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { found_arg_pattern: None, }; - // #40294: cause.body_id can also be a fn declaration. - // Currently, if it's anything other than NodeExpr, we just ignore it - match self.tcx.hir.find(body_id.node_id) { - Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr), - _ => () + if let Some(body_id) = body_id { + let expr = self.tcx.hir.expect_expr(body_id.node_id); + local_visitor.visit_expr(expr); } if let Some(pattern) = local_visitor.found_arg_pattern { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 247fb079fe7..64a6a0522cd 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -45,7 +45,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_fulfillment_errors(&self, - errors: &Vec>) { + errors: &Vec>, + body_id: Option) { #[derive(Debug)] struct ErrorDescriptor<'tcx> { predicate: ty::Predicate<'tcx>, @@ -105,7 +106,7 @@ struct ErrorDescriptor<'tcx> { for (error, suppressed) in errors.iter().zip(is_suppressed) { if !suppressed { - self.report_fulfillment_error(error); + self.report_fulfillment_error(error, body_id); } } } @@ -148,7 +149,8 @@ fn error_implies(&self, false } - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>, + body_id: Option) { debug!("report_fulfillment_errors({:?})", error); match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { @@ -158,7 +160,7 @@ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { self.report_projection_error(&error.obligation, e); } FulfillmentErrorCode::CodeAmbiguity => { - self.maybe_report_ambiguity(&error.obligation); + self.maybe_report_ambiguity(&error.obligation, body_id); } FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { self.report_mismatched_types(&error.obligation.cause, @@ -869,14 +871,14 @@ pub fn report_object_safety_error(self, } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, + body_id: Option) { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a // coherence violation, so we don't report it here. let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); - let body_id = hir::BodyId { node_id: obligation.cause.body_id }; let span = obligation.cause.span; debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", @@ -953,7 +955,7 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id }, + self.need_type_info(body_id, obligation.cause.span, a); } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e9196cd1243..056aad74600 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -498,7 +498,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { Ok(predicates) => predicates, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); // An unnormalized env is better than nothing. return elaborated_env; } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 91d6ce60b39..68b687a2e61 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -996,7 +996,7 @@ fn run_pass<'a, 'tcx>(&self, tcx.require_lang_item(lang_items::SyncTraitLangItem), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err); + infcx.report_fulfillment_errors(&err, None); } }); } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index fd5147d76e8..bf134f9547d 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -328,7 +328,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } @@ -793,7 +793,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return; } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 93057f91997..ed22cd1333e 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -110,7 +110,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a0afd58e586..dadf00944c6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -216,6 +216,8 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// environment is for an item or something where the "callee" is /// not clear. implicit_region_bound: Option>, + + body_id: Option, } impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { @@ -604,6 +606,7 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self { deferred_cast_checks: RefCell::new(Vec::new()), anon_types: RefCell::new(NodeMap()), implicit_region_bound, + body_id, } } @@ -2119,7 +2122,7 @@ fn select_all_obligations_or_error(&self) { match fulfillment_cx.select_all_or_error(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } @@ -2127,7 +2130,7 @@ fn select_all_obligations_or_error(&self) { fn select_obligations_where_possible(&self) { match self.fulfillment_cx.borrow_mut().select_where_possible(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 4af262bcb78..81e5dae5477 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -377,7 +377,7 @@ fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, span: &'cx Locatable, body: &'gcx hir: fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { - self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t); + self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); } } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index ccbc0299041..9305eff1436 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all transitive obligations are satisfied. if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 519e1ca6e5a..2857b5fb5e0 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -166,7 +166,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match fulfill_cx.select_all_or_error(infcx) { Ok(()) => true, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); false } } diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 28109747b75..129f7c8b1ea 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = |x| { - let_(add(x,x), |y| { //~ ERROR type annotations needed + let ex = |x| { //~ ERROR type annotations needed + let_(add(x,x), |y| { let_(add(x, x), |x|x)})}; }