Auto merge of #26859 - arielb1:const-deref-again, r=eddyb
Fixes #25901 r? @eddyb
This commit is contained in:
commit
fd8e175c4e
@ -1237,5 +1237,6 @@ register_diagnostics! {
|
||||
E0314, // closure outlives stack frame
|
||||
E0315, // cannot invoke closure outside of its lifetime
|
||||
E0316, // nested quantification of lifetimes
|
||||
E0370 // discriminant overflow
|
||||
E0370, // discriminant overflow
|
||||
E0400 // overloaded derefs are not allowed in constants
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
ast::ExprIndex(ref l, ref r) |
|
||||
ast::ExprBinary(_, ref l, ref r) if self.is_method_call(expr) => {
|
||||
ast::ExprBinary(_, ref l, ref r) if self.tcx.is_method_call(expr.id) => {
|
||||
self.call(expr, pred, &**l, Some(&**r).into_iter())
|
||||
}
|
||||
|
||||
@ -342,7 +342,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
self.straightline(expr, pred, fields)
|
||||
}
|
||||
|
||||
ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {
|
||||
ast::ExprUnary(_, ref e) if self.tcx.is_method_call(expr.id) => {
|
||||
self.call(expr, pred, &**e, None::<ast::Expr>.iter())
|
||||
}
|
||||
|
||||
@ -631,9 +631,4 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_method_call(&self, expr: &ast::Expr) -> bool {
|
||||
let method_call = ty::MethodCall::expr(expr.id);
|
||||
self.tcx.tables.borrow().method_map.contains_key(&method_call)
|
||||
}
|
||||
}
|
||||
|
@ -405,6 +405,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
||||
|
||||
let node_ty = self.tcx.node_id_to_type(ex.id);
|
||||
check_expr(self, ex, node_ty);
|
||||
check_adjustments(self, ex);
|
||||
|
||||
// Special-case some expressions to avoid certain flags bubbling up.
|
||||
match ex.node {
|
||||
@ -777,6 +778,25 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check the adjustments of an expression
|
||||
fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &ast::Expr) {
|
||||
match v.tcx.tables.borrow().adjustments.get(&e.id) {
|
||||
None | Some(&ty::AdjustReifyFnPointer) | Some(&ty::AdjustUnsafeFnPointer) => {}
|
||||
Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs, .. })) => {
|
||||
if (0..autoderefs as u32).any(|autoderef| {
|
||||
v.tcx.is_overloaded_autoderef(e.id, autoderef)
|
||||
}) {
|
||||
v.add_qualif(ConstQualif::NOT_CONST);
|
||||
if v.mode != Mode::Var {
|
||||
span_err!(v.tcx.sess, e.span, E0400,
|
||||
"user-defined dereference operators are not allowed in {}s",
|
||||
v.msg());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: &ty::ctxt) {
|
||||
visit::walk_crate(&mut CheckCrateVisitor {
|
||||
tcx: tcx,
|
||||
|
@ -6631,6 +6631,11 @@ impl<'tcx> ctxt<'tcx> {
|
||||
self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id))
|
||||
}
|
||||
|
||||
pub fn is_overloaded_autoderef(&self, expr_id: ast::NodeId, autoderefs: u32) -> bool {
|
||||
self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id,
|
||||
autoderefs))
|
||||
}
|
||||
|
||||
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
|
||||
Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
|
||||
}
|
||||
|
@ -367,8 +367,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
match datum.ty.sty {
|
||||
// Don't skip a conversion from Box<T> to &T, etc.
|
||||
ty::TyRef(..) => {
|
||||
let method_call = MethodCall::autoderef(expr.id, 0);
|
||||
if bcx.tcx().tables.borrow().method_map.contains_key(&method_call) {
|
||||
if bcx.tcx().is_overloaded_autoderef(expr.id, 0) {
|
||||
// Don't skip an overloaded deref.
|
||||
0
|
||||
} else {
|
||||
@ -1612,9 +1611,7 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
// The only overloaded operator that is translated to a datum
|
||||
// is an overloaded deref, since it is always yields a `&T`.
|
||||
// Otherwise, we should be in the RvalueDpsExpr path.
|
||||
assert!(
|
||||
op == ast::UnDeref ||
|
||||
!ccx.tcx().tables.borrow().method_map.contains_key(&method_call));
|
||||
assert!(op == ast::UnDeref || !ccx.tcx().is_method_call(expr.id));
|
||||
|
||||
let un_ty = expr_ty(bcx, expr);
|
||||
|
||||
@ -1907,7 +1904,7 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
// if overloaded, would be RvalueDpsExpr
|
||||
assert!(!ccx.tcx().tables.borrow().method_map.contains_key(&MethodCall::expr(expr.id)));
|
||||
assert!(!ccx.tcx().is_method_call(expr.id));
|
||||
|
||||
match op.node {
|
||||
ast::BiAnd => {
|
||||
@ -2141,7 +2138,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
debug!("trans_assign_op(expr={:?})", expr);
|
||||
|
||||
// User-defined operator methods cannot be used with `+=` etc right now
|
||||
assert!(!bcx.tcx().tables.borrow().method_map.contains_key(&MethodCall::expr(expr.id)));
|
||||
assert!(!bcx.tcx().is_method_call(expr.id));
|
||||
|
||||
// Evaluate LHS (destination), which should be an lvalue
|
||||
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
|
||||
@ -2606,7 +2603,7 @@ enum ExprKind {
|
||||
}
|
||||
|
||||
fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
|
||||
if tcx.tables.borrow().method_map.contains_key(&MethodCall::expr(expr.id)) {
|
||||
if tcx.is_method_call(expr.id) {
|
||||
// Overloaded operations are generally calls, and hence they are
|
||||
// generated via DPS, but there are a few exceptions:
|
||||
return match expr.node {
|
||||
|
@ -516,8 +516,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||
type_must_outlive(rcx, infer::ExprTypeIsNotInScope(expr_ty, expr.span),
|
||||
expr_ty, ty::ReScope(CodeExtent::from_node_id(expr.id)));
|
||||
|
||||
let method_call = MethodCall::expr(expr.id);
|
||||
let has_method_map = rcx.fcx.inh.tables.borrow().method_map.contains_key(&method_call);
|
||||
let has_method_map = rcx.fcx.infcx().is_method_call(expr.id);
|
||||
|
||||
// Check any autoderefs or autorefs that appear.
|
||||
let adjustment = rcx.fcx.inh.tables.borrow().adjustments.get(&expr.id).map(|a| a.clone());
|
||||
|
23
src/test/compile-fail/issue-25901.rs
Normal file
23
src/test/compile-fail/issue-25901.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct A;
|
||||
struct B;
|
||||
|
||||
static S: &'static B = &A; //~ ERROR user-defined dereference operators
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
impl Deref for A {
|
||||
type Target = B;
|
||||
fn deref(&self)->&B { static B_: B = B; &B_ }
|
||||
}
|
||||
|
||||
fn main(){}
|
Loading…
x
Reference in New Issue
Block a user