Skip to content

Commit 6f5baef

Browse files
committed
Check that fn arguments are WF when calling the fn. In combination with
invariance, this restores soundness to implied bounds (I think). :) Fixes rust-lang#25860.
1 parent 9c0413b commit 6f5baef

File tree

6 files changed

+91
-13
lines changed

6 files changed

+91
-13
lines changed

src/librustc/middle/ty.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,10 @@ pub struct ClosureUpvar<'tcx> {
16271627
}
16281628

16291629
impl Region {
1630+
pub fn from_node_id(node_id: ast::NodeId) -> Region {
1631+
ReScope(region::CodeExtent::from_node_id(node_id))
1632+
}
1633+
16301634
pub fn is_bound(&self) -> bool {
16311635
match *self {
16321636
ty::ReEarlyBound(..) => true,

src/librustc_typeck/check/callee.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
100100
}
101101

102102
Some(CallStep::Overloaded(method_callee)) => {
103-
confirm_overloaded_call(fcx, call_expr, callee_expr,
104-
arg_exprs, expected, method_callee);
103+
confirm_overloaded_call(fcx, call_expr, arg_exprs, expected, method_callee);
105104
}
106105
}
107106
}
@@ -262,6 +261,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
262261
&fn_sig.inputs);
263262
check_argument_types(fcx,
264263
call_expr.span,
264+
ty::Region::from_node_id(call_expr.id),
265265
&fn_sig.inputs,
266266
&expected_arg_tys[..],
267267
arg_exprs,
@@ -291,6 +291,7 @@ fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
291291

292292
check_argument_types(fcx,
293293
call_expr.span,
294+
ty::Region::from_node_id(call_expr.id),
294295
&*fn_sig.inputs,
295296
&*expected_arg_tys,
296297
arg_exprs,
@@ -301,17 +302,16 @@ fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
301302
}
302303

303304
fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
304-
call_expr: &ast::Expr,
305-
callee_expr: &'tcx ast::Expr,
305+
call_expr: &'tcx ast::Expr,
306306
arg_exprs: &'tcx [P<ast::Expr>],
307307
expected: Expectation<'tcx>,
308308
method_callee: ty::MethodCallee<'tcx>)
309309
{
310310
let output_type =
311311
check_method_argument_types(fcx,
312312
call_expr.span,
313+
call_expr,
313314
method_callee.ty,
314-
callee_expr,
315315
arg_exprs,
316316
TupleArgumentsFlag::TupleArguments,
317317
expected);

src/librustc_typeck/check/mod.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -2066,9 +2066,9 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
20662066
}
20672067

20682068
fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2069-
sp: Span,
2069+
span: Span,
2070+
call_expr: &'tcx ast::Expr,
20702071
method_fn_ty: Ty<'tcx>,
2071-
callee_expr: &'tcx ast::Expr,
20722072
args_no_rcvr: &'tcx [P<ast::Expr>],
20732073
tuple_arguments: TupleArgumentsFlag,
20742074
expected: Expectation<'tcx>)
@@ -2082,7 +2082,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
20822082
};
20832083

20842084
check_argument_types(fcx,
2085-
sp,
2085+
span,
2086+
ty::Region::from_node_id(call_expr.id),
20862087
&err_inputs[..],
20872088
&[],
20882089
args_no_rcvr,
@@ -2094,12 +2095,13 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
20942095
ty::TyBareFn(_, ref fty) => {
20952096
// HACK(eddyb) ignore self in the definition (see above).
20962097
let expected_arg_tys = expected_types_for_fn_args(fcx,
2097-
sp,
2098+
span,
20982099
expected,
20992100
fty.sig.0.output,
21002101
&fty.sig.0.inputs[1..]);
21012102
check_argument_types(fcx,
2102-
sp,
2103+
span,
2104+
ty::Region::from_node_id(call_expr.id),
21032105
&fty.sig.0.inputs[1..],
21042106
&expected_arg_tys[..],
21052107
args_no_rcvr,
@@ -2108,8 +2110,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
21082110
fty.sig.0.output
21092111
}
21102112
_ => {
2111-
fcx.tcx().sess.span_bug(callee_expr.span,
2112-
"method without bare fn type");
2113+
fcx.tcx().sess.span_bug(span, "method without bare fn type");
21132114
}
21142115
}
21152116
}
@@ -2119,13 +2120,21 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
21192120
/// operators.
21202121
fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
21212122
sp: Span,
2123+
call_scope: ty::Region,
21222124
fn_inputs: &[Ty<'tcx>],
21232125
expected_arg_tys: &[Ty<'tcx>],
21242126
args: &'tcx [P<ast::Expr>],
21252127
variadic: bool,
21262128
tuple_arguments: TupleArgumentsFlag) {
21272129
let tcx = fcx.ccx.tcx;
21282130

2131+
// All the input types from the fn signature must outlive the call
2132+
// so as to validate implied bounds.
2133+
for &fn_input_ty in fn_inputs {
2134+
let cause = traits::ObligationCause::misc(sp, fcx.body_id);
2135+
fcx.register_region_obligation(fn_input_ty, call_scope, cause);
2136+
}
2137+
21292138
// Grab the argument types, supplying fresh type variables
21302139
// if the wrong number of arguments were supplied
21312140
let supplied_arg_count = if tuple_arguments == DontTupleArguments {
@@ -2551,8 +2560,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
25512560
// Call the generic checker.
25522561
let ret_ty = check_method_argument_types(fcx,
25532562
method_name.span,
2554-
fn_ty,
25552563
expr,
2564+
fn_ty,
25562565
&args[1..],
25572566
DontTupleArguments,
25582567
expected);
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
static UNIT: &'static &'static () = &&();
12+
13+
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
14+
15+
fn bad<'a, T>(x: &'a T) -> &'static T {
16+
let f: fn(&'static &'static (), &'a T) -> &'static T = foo;
17+
//~^ ERROR cannot infer
18+
f(UNIT, x)
19+
}
20+
21+
fn main( ) { }
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
static UNIT: &'static &'static () = &&();
12+
13+
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
14+
15+
fn bad<'a, T>(x: &'a T) -> &'static T {
16+
foo(UNIT, x)
17+
//~^ ERROR cannot infer
18+
}
19+
20+
fn main() { }
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
static UNIT: &'static &'static () = &&();
12+
13+
trait Foo: Sized {
14+
fn foo<'a,'b,T>(self, _: &'a &'b (), v: &'b T) -> &'a T { v }
15+
}
16+
17+
impl Foo for () { }
18+
19+
fn bad<'a, T>(x: &'a T) -> &'static T {
20+
().foo(UNIT, x)
21+
//~^ ERROR cannot infer
22+
}
23+
24+
fn main() { }

0 commit comments

Comments
 (0)