summaryrefslogtreecommitdiffstats
path: root/src/test/ui/regions
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/regions')
-rw-r--r--src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs32
-rw-r--r--src/test/ui/regions/closure-in-projection-issue-97405.rs32
-rw-r--r--src/test/ui/regions/closure-in-projection-issue-97405.stderr30
-rw-r--r--src/test/ui/regions/forall-wf-ref-reflexive.rs18
-rw-r--r--src/test/ui/regions/forall-wf-ref-reflexive.stderr8
-rw-r--r--src/test/ui/regions/forall-wf-reflexive.rs15
-rw-r--r--src/test/ui/regions/init-res-into-things.rs81
-rw-r--r--src/test/ui/regions/issue-12470.rs34
-rw-r--r--src/test/ui/regions/issue-12470.stderr11
-rw-r--r--src/test/ui/regions/issue-21520.rs22
-rw-r--r--src/test/ui/regions/issue-24085.rs19
-rw-r--r--src/test/ui/regions/issue-26448-1.rs13
-rw-r--r--src/test/ui/regions/issue-26448-2.rs21
-rw-r--r--src/test/ui/regions/issue-26448-3.rs25
-rw-r--r--src/test/ui/regions/issue-2718.rs327
-rw-r--r--src/test/ui/regions/issue-28848.rs14
-rw-r--r--src/test/ui/regions/issue-28848.stderr14
-rw-r--r--src/test/ui/regions/issue-5243.rs17
-rw-r--r--src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs67
-rw-r--r--src/test/ui/regions/issue-6157.rs23
-rw-r--r--src/test/ui/regions/issue-72051-member-region-hang.rs7
-rw-r--r--src/test/ui/regions/issue-78262.base.stderr14
-rw-r--r--src/test/ui/regions/issue-78262.polonius.stderr14
-rw-r--r--src/test/ui/regions/issue-78262.rs15
-rw-r--r--src/test/ui/regions/owned-implies-static.rs8
-rw-r--r--src/test/ui/regions/rcvr-borrowed-to-region.rs28
-rw-r--r--src/test/ui/regions/region-borrow-params-issue-29793-big.rs74
-rw-r--r--src/test/ui/regions/region-borrow-params-issue-29793-big.stderr39
-rw-r--r--src/test/ui/regions/region-borrow-params-issue-29793-small.rs212
-rw-r--r--src/test/ui/regions/region-borrow-params-issue-29793-small.stderr363
-rw-r--r--src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs16
-rw-r--r--src/test/ui/regions/region-bound-on-closure-outlives-call.rs6
-rw-r--r--src/test/ui/regions/region-bound-on-closure-outlives-call.stderr24
-rw-r--r--src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs17
-rw-r--r--src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs36
-rw-r--r--src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr35
-rw-r--r--src/test/ui/regions/region-invariant-static-error-reporting.rs21
-rw-r--r--src/test/ui/regions/region-invariant-static-error-reporting.stderr21
-rw-r--r--src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs30
-rw-r--r--src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr12
-rw-r--r--src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs32
-rw-r--r--src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr12
-rw-r--r--src/test/ui/regions/region-object-lifetime-1.rs18
-rw-r--r--src/test/ui/regions/region-object-lifetime-2.rs14
-rw-r--r--src/test/ui/regions/region-object-lifetime-2.stderr14
-rw-r--r--src/test/ui/regions/region-object-lifetime-3.rs18
-rw-r--r--src/test/ui/regions/region-object-lifetime-4.rs16
-rw-r--r--src/test/ui/regions/region-object-lifetime-4.stderr14
-rw-r--r--src/test/ui/regions/region-object-lifetime-5.rs14
-rw-r--r--src/test/ui/regions/region-object-lifetime-5.stderr9
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.rs34
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.stderr62
-rw-r--r--src/test/ui/regions/regions-addr-of-arg.rs17
-rw-r--r--src/test/ui/regions/regions-addr-of-arg.stderr20
-rw-r--r--src/test/ui/regions/regions-addr-of-interior-of-unique-box.rs23
-rw-r--r--src/test/ui/regions/regions-addr-of-ret.rs9
-rw-r--r--src/test/ui/regions/regions-addr-of-self.rs28
-rw-r--r--src/test/ui/regions/regions-addr-of-self.stderr10
-rw-r--r--src/test/ui/regions/regions-addr-of-upvar-self.rs18
-rw-r--r--src/test/ui/regions/regions-addr-of-upvar-self.stderr35
-rw-r--r--src/test/ui/regions/regions-adjusted-lvalue-op.rs16
-rw-r--r--src/test/ui/regions/regions-adjusted-lvalue-op.stderr21
-rw-r--r--src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs41
-rw-r--r--src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr15
-rw-r--r--src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs24
-rw-r--r--src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr27
-rw-r--r--src/test/ui/regions/regions-assoc-type-region-bound.rs22
-rw-r--r--src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs19
-rw-r--r--src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr15
-rw-r--r--src/test/ui/regions/regions-assoc-type-static-bound.rs19
-rw-r--r--src/test/ui/regions/regions-borrow-at.rs12
-rw-r--r--src/test/ui/regions/regions-borrow-evec-fixed.rs10
-rw-r--r--src/test/ui/regions/regions-borrow-evec-uniq.rs16
-rw-r--r--src/test/ui/regions/regions-borrow-uniq.rs11
-rw-r--r--src/test/ui/regions/regions-bot.rs11
-rw-r--r--src/test/ui/regions/regions-bound-lists-feature-gate-2.rs14
-rw-r--r--src/test/ui/regions/regions-bound-lists-feature-gate.rs18
-rw-r--r--src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs69
-rw-r--r--src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr50
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs24
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr18
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs29
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr18
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters.rs16
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters.stderr10
-rw-r--r--src/test/ui/regions/regions-bounds.rs18
-rw-r--r--src/test/ui/regions/regions-bounds.stderr26
-rw-r--r--src/test/ui/regions/regions-close-associated-type-into-object.rs71
-rw-r--r--src/test/ui/regions/regions-close-associated-type-into-object.stderr40
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-1.rs15
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-1.stderr12
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.rs14
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.stderr29
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-3.rs14
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-3.stderr12
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.rs19
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.stderr74
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-5.rs25
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-5.stderr57
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-1.rs24
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-1.stderr26
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-multiple.rs24
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr15
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-successfully.rs21
-rw-r--r--src/test/ui/regions/regions-close-param-into-object.rs27
-rw-r--r--src/test/ui/regions/regions-close-param-into-object.stderr48
-rw-r--r--src/test/ui/regions/regions-copy-closure.rs21
-rw-r--r--src/test/ui/regions/regions-creating-enums.rs33
-rw-r--r--src/test/ui/regions/regions-creating-enums.stderr21
-rw-r--r--src/test/ui/regions/regions-creating-enums2.rs17
-rw-r--r--src/test/ui/regions/regions-creating-enums3.rs12
-rw-r--r--src/test/ui/regions/regions-creating-enums3.stderr14
-rw-r--r--src/test/ui/regions/regions-creating-enums4.rs12
-rw-r--r--src/test/ui/regions/regions-creating-enums4.stderr14
-rw-r--r--src/test/ui/regions/regions-creating-enums5.rs17
-rw-r--r--src/test/ui/regions/regions-debruijn-of-object.rs22
-rw-r--r--src/test/ui/regions/regions-dependent-addr-of.rs112
-rw-r--r--src/test/ui/regions/regions-dependent-autofn.rs15
-rw-r--r--src/test/ui/regions/regions-dependent-autoslice.rs14
-rw-r--r--src/test/ui/regions/regions-dependent-let-ref.rs12
-rw-r--r--src/test/ui/regions/regions-early-bound-error-method.rs26
-rw-r--r--src/test/ui/regions/regions-early-bound-error-method.stderr14
-rw-r--r--src/test/ui/regions/regions-early-bound-error.rs24
-rw-r--r--src/test/ui/regions/regions-early-bound-error.stderr14
-rw-r--r--src/test/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs35
-rw-r--r--src/test/ui/regions/regions-early-bound-trait-param.rs132
-rw-r--r--src/test/ui/regions/regions-early-bound-used-in-bound-method.rs30
-rw-r--r--src/test/ui/regions/regions-early-bound-used-in-bound.rs28
-rw-r--r--src/test/ui/regions/regions-early-bound-used-in-type-param.rs28
-rw-r--r--src/test/ui/regions/regions-escape-into-other-fn.rs8
-rw-r--r--src/test/ui/regions/regions-escape-method.rs16
-rw-r--r--src/test/ui/regions/regions-escape-method.stderr11
-rw-r--r--src/test/ui/regions/regions-escape-via-trait-or-not.rs22
-rw-r--r--src/test/ui/regions/regions-escape-via-trait-or-not.stderr11
-rw-r--r--src/test/ui/regions/regions-expl-self.rs15
-rw-r--r--src/test/ui/regions/regions-fn-subtyping-2.rs20
-rw-r--r--src/test/ui/regions/regions-fn-subtyping-return-static-fail.rs51
-rw-r--r--src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr19
-rw-r--r--src/test/ui/regions/regions-fn-subtyping-return-static.rs48
-rw-r--r--src/test/ui/regions/regions-fn-subtyping.rs30
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-callee-4.rs11
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-callee-4.stderr20
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-callee.rs30
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-callee.stderr28
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller.rs23
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller.stderr39
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller1.rs14
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller1.stderr32
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-incorrect.rs22
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-incorrect.stderr17
-rw-r--r--src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs17
-rw-r--r--src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr10
-rw-r--r--src/test/ui/regions/regions-glb-free-free.rs29
-rw-r--r--src/test/ui/regions/regions-glb-free-free.stderr16
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs30
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr14
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs23
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs23
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs23
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs26
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr14
-rw-r--r--src/test/ui/regions/regions-in-enums-anon.rs7
-rw-r--r--src/test/ui/regions/regions-in-enums-anon.stderr15
-rw-r--r--src/test/ui/regions/regions-in-enums.rs20
-rw-r--r--src/test/ui/regions/regions-in-enums.stderr19
-rw-r--r--src/test/ui/regions/regions-in-structs-anon.rs7
-rw-r--r--src/test/ui/regions/regions-in-structs-anon.stderr15
-rw-r--r--src/test/ui/regions/regions-in-structs.rs15
-rw-r--r--src/test/ui/regions/regions-in-structs.stderr20
-rw-r--r--src/test/ui/regions/regions-infer-at-fn-not-param.rs19
-rw-r--r--src/test/ui/regions/regions-infer-at-fn-not-param.stderr11
-rw-r--r--src/test/ui/regions/regions-infer-borrow-scope-addr-of.rs23
-rw-r--r--src/test/ui/regions/regions-infer-borrow-scope-too-big.rs16
-rw-r--r--src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr12
-rw-r--r--src/test/ui/regions/regions-infer-borrow-scope-view.rs11
-rw-r--r--src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs12
-rw-r--r--src/test/ui/regions/regions-infer-borrow-scope.rs14
-rw-r--r--src/test/ui/regions/regions-infer-bound-from-trait-self.rs51
-rw-r--r--src/test/ui/regions/regions-infer-bound-from-trait-self.stderr12
-rw-r--r--src/test/ui/regions/regions-infer-bound-from-trait.rs40
-rw-r--r--src/test/ui/regions/regions-infer-bound-from-trait.stderr25
-rw-r--r--src/test/ui/regions/regions-infer-call-2.rs15
-rw-r--r--src/test/ui/regions/regions-infer-call-3.rs14
-rw-r--r--src/test/ui/regions/regions-infer-call-3.stderr11
-rw-r--r--src/test/ui/regions/regions-infer-call.rs11
-rw-r--r--src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs29
-rw-r--r--src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr15
-rw-r--r--src/test/ui/regions/regions-infer-contravariance-due-to-ret.rs22
-rw-r--r--src/test/ui/regions/regions-infer-covariance-due-to-decl.rs26
-rw-r--r--src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr15
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-decl.rs17
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr14
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs15
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr14
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs15
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr14
-rw-r--r--src/test/ui/regions/regions-infer-not-param.rs24
-rw-r--r--src/test/ui/regions/regions-infer-not-param.stderr40
-rw-r--r--src/test/ui/regions/regions-infer-paramd-indirect.rs27
-rw-r--r--src/test/ui/regions/regions-infer-paramd-indirect.stderr13
-rw-r--r--src/test/ui/regions/regions-infer-proc-static-upvar.rs24
-rw-r--r--src/test/ui/regions/regions-infer-proc-static-upvar.stderr15
-rw-r--r--src/test/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs18
-rw-r--r--src/test/ui/regions/regions-infer-region-in-fn-but-not-type.rs19
-rw-r--r--src/test/ui/regions/regions-infer-static-from-proc.rs18
-rw-r--r--src/test/ui/regions/regions-issue-21422.rs18
-rw-r--r--src/test/ui/regions/regions-issue-22246.rs29
-rw-r--r--src/test/ui/regions/regions-lifetime-bounds-on-fns.rs30
-rw-r--r--src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr12
-rw-r--r--src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs33
-rw-r--r--src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs26
-rw-r--r--src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr19
-rw-r--r--src/test/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs20
-rw-r--r--src/test/ui/regions/regions-link-fn-args.rs15
-rw-r--r--src/test/ui/regions/regions-lub-ref-ref-rc.rs28
-rw-r--r--src/test/ui/regions/regions-mock-codegen.rs54
-rw-r--r--src/test/ui/regions/regions-name-duplicated.rs6
-rw-r--r--src/test/ui/regions/regions-name-duplicated.stderr11
-rw-r--r--src/test/ui/regions/regions-name-static.rs6
-rw-r--r--src/test/ui/regions/regions-name-static.stderr9
-rw-r--r--src/test/ui/regions/regions-name-undeclared.rs58
-rw-r--r--src/test/ui/regions/regions-name-undeclared.stderr156
-rw-r--r--src/test/ui/regions/regions-nested-fns-2.rs12
-rw-r--r--src/test/ui/regions/regions-nested-fns-2.stderr17
-rw-r--r--src/test/ui/regions/regions-nested-fns.rs24
-rw-r--r--src/test/ui/regions/regions-nested-fns.stderr52
-rw-r--r--src/test/ui/regions/regions-no-bound-in-argument-cleanup.rs24
-rw-r--r--src/test/ui/regions/regions-no-variance-from-fn-generics.rs44
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.rs31
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.stderr27
-rw-r--r--src/test/ui/regions/regions-nullary-variant.rs15
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs20
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-hrtb.rs52
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr28
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-wc.rs35
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-wc.stderr15
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container.rs77
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container.stderr54
-rw-r--r--src/test/ui/regions/regions-outlives-projection-hrtype.rs26
-rw-r--r--src/test/ui/regions/regions-outlives-projection-trait-def.rs21
-rw-r--r--src/test/ui/regions/regions-outlives-scalar.rs13
-rw-r--r--src/test/ui/regions/regions-params.rs19
-rw-r--r--src/test/ui/regions/regions-pattern-typing-issue-19552.rs8
-rw-r--r--src/test/ui/regions/regions-pattern-typing-issue-19552.stderr14
-rw-r--r--src/test/ui/regions/regions-pattern-typing-issue-19997.rs11
-rw-r--r--src/test/ui/regions/regions-pattern-typing-issue-19997.stderr14
-rw-r--r--src/test/ui/regions/regions-proc-bound-capture.rs13
-rw-r--r--src/test/ui/regions/regions-proc-bound-capture.stderr20
-rw-r--r--src/test/ui/regions/regions-reassign-let-bound-pointer.rs18
-rw-r--r--src/test/ui/regions/regions-reassign-match-bound-pointer.rs21
-rw-r--r--src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs9
-rw-r--r--src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr14
-rw-r--r--src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs16
-rw-r--r--src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr14
-rw-r--r--src/test/ui/regions/regions-ref-in-fn-arg.rs14
-rw-r--r--src/test/ui/regions/regions-ref-in-fn-arg.stderr19
-rw-r--r--src/test/ui/regions/regions-refcell.rs45
-rw-r--r--src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs57
-rw-r--r--src/test/ui/regions/regions-ret-borrowed-1.rs17
-rw-r--r--src/test/ui/regions/regions-ret-borrowed-1.stderr11
-rw-r--r--src/test/ui/regions/regions-ret-borrowed.rs20
-rw-r--r--src/test/ui/regions/regions-ret-borrowed.stderr11
-rw-r--r--src/test/ui/regions/regions-ret.rs8
-rw-r--r--src/test/ui/regions/regions-ret.stderr12
-rw-r--r--src/test/ui/regions/regions-return-interior-of-option.rs24
-rw-r--r--src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs11
-rw-r--r--src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr17
-rw-r--r--src/test/ui/regions/regions-return-stack-allocated-vec.rs10
-rw-r--r--src/test/ui/regions/regions-return-stack-allocated-vec.stderr12
-rw-r--r--src/test/ui/regions/regions-scope-chain-example.rs43
-rw-r--r--src/test/ui/regions/regions-self-impls.rs20
-rw-r--r--src/test/ui/regions/regions-self-in-enums.rs17
-rw-r--r--src/test/ui/regions/regions-simple.rs7
-rw-r--r--src/test/ui/regions/regions-static-bound-rpass.rs26
-rw-r--r--src/test/ui/regions/regions-static-bound-rpass.stderr26
-rw-r--r--src/test/ui/regions/regions-static-bound.rs21
-rw-r--r--src/test/ui/regions/regions-static-bound.stderr54
-rw-r--r--src/test/ui/regions/regions-static-closure.rs19
-rw-r--r--src/test/ui/regions/regions-steal-closure.rs17
-rw-r--r--src/test/ui/regions/regions-steal-closure.stderr16
-rw-r--r--src/test/ui/regions/regions-trait-1.rs33
-rw-r--r--src/test/ui/regions/regions-trait-object-1.rs35
-rw-r--r--src/test/ui/regions/regions-trait-object-subtyping.rs26
-rw-r--r--src/test/ui/regions/regions-trait-object-subtyping.stderr34
-rw-r--r--src/test/ui/regions/regions-trait-variance.rs44
-rw-r--r--src/test/ui/regions/regions-trait-variance.stderr11
-rw-r--r--src/test/ui/regions/regions-undeclared.rs13
-rw-r--r--src/test/ui/regions/regions-undeclared.stderr42
-rw-r--r--src/test/ui/regions/regions-var-type-out-of-scope.rs14
-rw-r--r--src/test/ui/regions/regions-var-type-out-of-scope.stderr15
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs27
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs29
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr15
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-covariant.rs27
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr15
-rw-r--r--src/test/ui/regions/regions-variance-covariant-use-contravariant.rs27
-rw-r--r--src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr15
-rw-r--r--src/test/ui/regions/regions-variance-covariant-use-covariant.rs23
-rw-r--r--src/test/ui/regions/regions-variance-invariant-use-contravariant.rs24
-rw-r--r--src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr18
-rw-r--r--src/test/ui/regions/regions-variance-invariant-use-covariant.rs21
-rw-r--r--src/test/ui/regions/regions-variance-invariant-use-covariant.stderr15
-rw-r--r--src/test/ui/regions/regions-wf-trait-object.rs10
-rw-r--r--src/test/ui/regions/regions-wf-trait-object.stderr20
-rw-r--r--src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs66
-rw-r--r--src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs35
-rw-r--r--src/test/ui/regions/wf-bound-region-in-object-type.rs22
314 files changed, 8254 insertions, 0 deletions
diff --git a/src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs b/src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs
new file mode 100644
index 000000000..ce2a3a7db
--- /dev/null
+++ b/src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs
@@ -0,0 +1,32 @@
+// Check that method bounds declared on traits/impls in a cross-crate
+// scenario work. This is the library portion of the test.
+
+pub enum MaybeOwned<'a> {
+ Owned(isize),
+ Borrowed(&'a isize)
+}
+
+pub struct Inv<'a> { // invariant w/r/t 'a
+ x: &'a mut &'a isize
+}
+
+// I encountered a bug at some point with encoding the IntoMaybeOwned
+// trait, so I'll use that as the template for this test.
+pub trait IntoMaybeOwned<'a> {
+ fn into_maybe_owned(self) -> MaybeOwned<'a>;
+
+ // Note: without this `into_inv` method, the trait is
+ // contravariant w/r/t `'a`, since if you look strictly at the
+ // interface, it only returns `'a`. This complicates the
+ // downstream test since it wants invariance to force an error.
+ // Hence we add this method.
+ fn into_inv(self) -> Inv<'a>;
+
+ fn bigger_region<'b:'a>(self, b: Inv<'b>);
+}
+
+impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
+ fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
+ fn into_inv(self) -> Inv<'a> { panic!() }
+ fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
+}
diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.rs b/src/test/ui/regions/closure-in-projection-issue-97405.rs
new file mode 100644
index 000000000..e567d5c27
--- /dev/null
+++ b/src/test/ui/regions/closure-in-projection-issue-97405.rs
@@ -0,0 +1,32 @@
+// Regression test for #97405.
+// In `good_generic_fn` the param `T` ends up in the substs of closures/generators,
+// but we should be able to prove `<Gen<T> as Iterator>::Item: 'static` without
+// requiring `T: 'static`
+
+// edition:2018
+// check-fail
+
+fn opaque<F>(_: F) -> impl Iterator { b"".iter() }
+
+fn assert_static<T: 'static>(_: T) {}
+
+fn good_generic_fn<T>() {
+ // Previously, proving `<OpaqueTy<type_of(async {})> as Iterator>::Item: 'static`
+ // used to require `T: 'static`.
+ assert_static(opaque(async {}).next());
+ assert_static(opaque(|| {}).next());
+ assert_static(opaque(opaque(async {}).next()).next());
+}
+
+
+// This should fail because `T` ends up in the upvars of the closure.
+fn bad_generic_fn<T: Copy>(t: T) {
+ assert_static(opaque(async move { t; }).next());
+ //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ assert_static(opaque(move || { t; }).next());
+ //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ assert_static(opaque(opaque(async move { t; }).next()).next());
+ //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.stderr b/src/test/ui/regions/closure-in-projection-issue-97405.stderr
new file mode 100644
index 000000000..c08f1059e
--- /dev/null
+++ b/src/test/ui/regions/closure-in-projection-issue-97405.stderr
@@ -0,0 +1,30 @@
+error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ --> $DIR/closure-in-projection-issue-97405.rs:24:5
+ |
+LL | assert_static(opaque(async move { t; }).next());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
+ = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+
+error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ --> $DIR/closure-in-projection-issue-97405.rs:26:5
+ |
+LL | assert_static(opaque(move || { t; }).next());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
+ = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+
+error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ --> $DIR/closure-in-projection-issue-97405.rs:28:5
+ |
+LL | assert_static(opaque(opaque(async move { t; }).next()).next());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
+ = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/forall-wf-ref-reflexive.rs b/src/test/ui/regions/forall-wf-ref-reflexive.rs
new file mode 100644
index 000000000..9c37d72d5
--- /dev/null
+++ b/src/test/ui/regions/forall-wf-ref-reflexive.rs
@@ -0,0 +1,18 @@
+// Test that we consider `for<'a> &'a T: 'a` to be sufficient to prove
+// that `for<'a> &'a T: 'a`.
+//
+// FIXME. Except we don't!
+
+#![allow(warnings)]
+
+fn self_wf2<T>()
+where
+ for<'a> &'a T: 'a,
+{
+ self_wf2::<T>();
+ //~^ ERROR `T` does not live long enough
+ //
+ // FIXME. This ought to be accepted, presumably.
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/forall-wf-ref-reflexive.stderr b/src/test/ui/regions/forall-wf-ref-reflexive.stderr
new file mode 100644
index 000000000..3d059ccec
--- /dev/null
+++ b/src/test/ui/regions/forall-wf-ref-reflexive.stderr
@@ -0,0 +1,8 @@
+error: `T` does not live long enough
+ --> $DIR/forall-wf-ref-reflexive.rs:12:5
+ |
+LL | self_wf2::<T>();
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/forall-wf-reflexive.rs b/src/test/ui/regions/forall-wf-reflexive.rs
new file mode 100644
index 000000000..8e6b8224b
--- /dev/null
+++ b/src/test/ui/regions/forall-wf-reflexive.rs
@@ -0,0 +1,15 @@
+// Test that we consider `for<'a> T: 'a` to be sufficient to prove
+// that `for<'a> T: 'a`.
+//
+// check-pass
+
+#![allow(warnings)]
+
+fn self_wf1<T>()
+where
+ for<'a> T: 'a,
+{
+ self_wf1::<T>();
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/init-res-into-things.rs b/src/test/ui/regions/init-res-into-things.rs
new file mode 100644
index 000000000..7f416262d
--- /dev/null
+++ b/src/test/ui/regions/init-res-into-things.rs
@@ -0,0 +1,81 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
+use std::cell::Cell;
+
+// Resources can't be copied, but storing into data structures counts
+// as a move unless the stored thing is used afterwards.
+
+struct r<'a> {
+ i: &'a Cell<isize>,
+}
+
+struct BoxR<'a> { x: r<'a> }
+
+impl<'a> Drop for r<'a> {
+ fn drop(&mut self) {
+ self.i.set(self.i.get() + 1)
+ }
+}
+
+fn r(i: &Cell<isize>) -> r {
+ r {
+ i: i
+ }
+}
+
+fn test_rec() {
+ let i = &Cell::new(0);
+ {
+ let _a = BoxR {x: r(i)};
+ }
+ assert_eq!(i.get(), 1);
+}
+
+fn test_tag() {
+ enum t<'a> {
+ t0(r<'a>),
+ }
+
+ let i = &Cell::new(0);
+ {
+ let _a = t::t0(r(i));
+ }
+ assert_eq!(i.get(), 1);
+}
+
+fn test_tup() {
+ let i = &Cell::new(0);
+ {
+ let _a = (r(i), 0);
+ }
+ assert_eq!(i.get(), 1);
+}
+
+fn test_unique() {
+ let i = &Cell::new(0);
+ {
+ let _a: Box<_> = Box::new(r(i));
+ }
+ assert_eq!(i.get(), 1);
+}
+
+fn test_unique_rec() {
+ let i = &Cell::new(0);
+ {
+ let _a: Box<_> = Box::new(BoxR {
+ x: r(i)
+ });
+ }
+ assert_eq!(i.get(), 1);
+}
+
+pub fn main() {
+ test_rec();
+ test_tag();
+ test_tup();
+ test_unique();
+ test_unique_rec();
+}
diff --git a/src/test/ui/regions/issue-12470.rs b/src/test/ui/regions/issue-12470.rs
new file mode 100644
index 000000000..d8f2abb0c
--- /dev/null
+++ b/src/test/ui/regions/issue-12470.rs
@@ -0,0 +1,34 @@
+trait X {
+ fn get_i(&self) -> isize;
+}
+
+
+
+
+struct B {
+ i: isize
+}
+
+impl X for B {
+ fn get_i(&self) -> isize {
+ self.i
+ }
+}
+
+struct A<'a> {
+ p: &'a (dyn X + 'a)
+}
+
+fn make_a<'a>(p: &'a dyn X) -> A<'a> {
+ A { p: p }
+}
+
+fn make_make_a<'a>() -> A<'a> {
+ let b: Box<B> = Box::new(B { i: 1 });
+ let bb: &B = &*b;
+ make_a(bb) //~ ERROR cannot return value referencing local data `*b`
+}
+
+fn main() {
+ let _a = make_make_a();
+}
diff --git a/src/test/ui/regions/issue-12470.stderr b/src/test/ui/regions/issue-12470.stderr
new file mode 100644
index 000000000..c97e59195
--- /dev/null
+++ b/src/test/ui/regions/issue-12470.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing local data `*b`
+ --> $DIR/issue-12470.rs:29:5
+ |
+LL | let bb: &B = &*b;
+ | --- `*b` is borrowed here
+LL | make_a(bb)
+ | ^^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/issue-21520.rs b/src/test/ui/regions/issue-21520.rs
new file mode 100644
index 000000000..ab4ac7237
--- /dev/null
+++ b/src/test/ui/regions/issue-21520.rs
@@ -0,0 +1,22 @@
+// check-pass
+#![allow(dead_code)]
+// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
+// not wind up propagating to `T`.
+
+// pretty-expanded FIXME #23616
+
+pub trait Foo {
+ type Bar;
+
+ fn foo(&self) -> Self;
+}
+
+pub struct Static<T:'static>(T);
+
+struct Bar<T:Foo>
+ where T::Bar : 'static
+{
+ x: Static<Option<T::Bar>>
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/issue-24085.rs b/src/test/ui/regions/issue-24085.rs
new file mode 100644
index 000000000..86e94beb7
--- /dev/null
+++ b/src/test/ui/regions/issue-24085.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![allow(dead_code)]
+// Regression test for #24085. Errors were occurring in region
+// inference due to the requirement that `'a:b'`, which was getting
+// incorrectly codegened in connection with the closure below.
+
+#[derive(Copy,Clone)]
+struct Path<'a:'b, 'b> {
+ x: &'a i32,
+ tail: Option<&'b Path<'a, 'b>>
+}
+
+#[allow(dead_code, unconditional_recursion)]
+fn foo<'a,'b,F>(p: Path<'a, 'b>, mut f: F)
+ where F: for<'c> FnMut(Path<'a, 'c>) {
+ foo(p, |x| f(x))
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/issue-26448-1.rs b/src/test/ui/regions/issue-26448-1.rs
new file mode 100644
index 000000000..7d2d75bf2
--- /dev/null
+++ b/src/test/ui/regions/issue-26448-1.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+pub trait Foo<T> {
+ fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+ fn foo(self) -> T {
+ panic!();
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-26448-2.rs b/src/test/ui/regions/issue-26448-2.rs
new file mode 100644
index 000000000..c60e06c3c
--- /dev/null
+++ b/src/test/ui/regions/issue-26448-2.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+pub struct Bar<T> {
+ items: Vec<&'static str>,
+ inner: T,
+}
+
+pub trait IntoBar<T> {
+ fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+ fn into_bar(self) -> Bar<T> {
+ Bar {
+ items: Vec::new(),
+ inner: self.into(),
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-26448-3.rs b/src/test/ui/regions/issue-26448-3.rs
new file mode 100644
index 000000000..d48022c09
--- /dev/null
+++ b/src/test/ui/regions/issue-26448-3.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+pub struct Item {
+ _inner: &'static str,
+}
+
+pub struct Bar<T> {
+ items: Vec<Item>,
+ inner: T,
+}
+
+pub trait IntoBar<T> {
+ fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+ fn into_bar(self) -> Bar<T> {
+ Bar {
+ items: Vec::new(),
+ inner: self.into(),
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-2718.rs b/src/test/ui/regions/issue-2718.rs
new file mode 100644
index 000000000..6449337ee
--- /dev/null
+++ b/src/test/ui/regions/issue-2718.rs
@@ -0,0 +1,327 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_unsafe)]
+#![allow(unused_imports)]
+#![allow(non_camel_case_types)]
+
+pub type Task = isize;
+
+// tjc: I don't know why
+pub mod pipes {
+ use self::state::{empty, full, blocked, terminated};
+ use super::Task;
+ use std::mem::{forget, transmute};
+ use std::mem::{replace, swap};
+ use std::mem;
+ use std::thread;
+ use std::marker::Send;
+
+ pub struct Stuff<T> {
+ state: state,
+ blocked_task: Option<Task>,
+ payload: Option<T>
+ }
+
+ #[derive(PartialEq, Debug)]
+ #[repr(isize)]
+ pub enum state {
+ empty,
+ full,
+ blocked,
+ terminated
+ }
+
+ pub struct packet<T> {
+ state: state,
+ blocked_task: Option<Task>,
+ payload: Option<T>
+ }
+
+ unsafe impl<T:Send> Send for packet<T> {}
+
+ pub fn packet<T:Send>() -> *const packet<T> {
+ unsafe {
+ let p: *const packet<T> = mem::transmute(Box::new(Stuff{
+ state: empty,
+ blocked_task: None::<Task>,
+ payload: None::<T>
+ }));
+ p
+ }
+ }
+
+ mod rusti {
+ pub fn atomic_xchg(_dst: &mut isize, _src: isize) -> isize { panic!(); }
+ pub fn atomic_xchg_acq(_dst: &mut isize, _src: isize) -> isize { panic!(); }
+ pub fn atomic_xchg_rel(_dst: &mut isize, _src: isize) -> isize { panic!(); }
+ }
+
+ // We should consider moving this to ::std::unsafe, although I
+ // suspect graydon would want us to use void pointers instead.
+ pub unsafe fn uniquify<T>(x: *const T) -> Box<T> {
+ mem::transmute(x)
+ }
+
+ pub fn swap_state_acq(dst: &mut state, src: state) -> state {
+ unsafe {
+ transmute(rusti::atomic_xchg_acq(transmute(dst), src as isize))
+ }
+ }
+
+ pub fn swap_state_rel(dst: &mut state, src: state) -> state {
+ unsafe {
+ transmute(rusti::atomic_xchg_rel(transmute(dst), src as isize))
+ }
+ }
+
+ pub fn send<T:Send>(mut p: send_packet<T>, payload: T) {
+ let p = p.unwrap();
+ let mut p = unsafe { uniquify(p) };
+ assert!((*p).payload.is_none());
+ (*p).payload = Some(payload);
+ let old_state = swap_state_rel(&mut (*p).state, full);
+ match old_state {
+ empty => {
+ // Yay, fastpath.
+
+ // The receiver will eventually clean this up.
+ unsafe { forget(p); }
+ }
+ full => { panic!("duplicate send") }
+ blocked => {
+
+ // The receiver will eventually clean this up.
+ unsafe { forget(p); }
+ }
+ terminated => {
+ // The receiver will never receive this. Rely on drop_glue
+ // to clean everything up.
+ }
+ }
+ }
+
+ pub fn recv<T:Send>(mut p: recv_packet<T>) -> Option<T> {
+ let p = p.unwrap();
+ let mut p = unsafe { uniquify(p) };
+ loop {
+ let old_state = swap_state_acq(&mut (*p).state,
+ blocked);
+ match old_state {
+ empty | blocked => { thread::yield_now(); }
+ full => {
+ let payload = replace(&mut p.payload, None);
+ return Some(payload.unwrap())
+ }
+ terminated => {
+ assert_eq!(old_state, terminated);
+ return None;
+ }
+ }
+ }
+ }
+
+ pub fn sender_terminate<T:Send>(p: *const packet<T>) {
+ let mut p = unsafe { uniquify(p) };
+ match swap_state_rel(&mut (*p).state, terminated) {
+ empty | blocked => {
+ // The receiver will eventually clean up.
+ unsafe { forget(p) }
+ }
+ full => {
+ // This is impossible
+ panic!("you dun goofed")
+ }
+ terminated => {
+ // I have to clean up, use drop_glue
+ }
+ }
+ }
+
+ pub fn receiver_terminate<T:Send>(p: *const packet<T>) {
+ let mut p = unsafe { uniquify(p) };
+ match swap_state_rel(&mut (*p).state, terminated) {
+ empty => {
+ // the sender will clean up
+ unsafe { forget(p) }
+ }
+ blocked => {
+ // this shouldn't happen.
+ panic!("terminating a blocked packet")
+ }
+ terminated | full => {
+ // I have to clean up, use drop_glue
+ }
+ }
+ }
+
+ pub struct send_packet<T:Send> {
+ p: Option<*const packet<T>>,
+ }
+
+ impl<T:Send> Drop for send_packet<T> {
+ fn drop(&mut self) {
+ unsafe {
+ if self.p != None {
+ let self_p: &mut Option<*const packet<T>> =
+ mem::transmute(&mut self.p);
+ let p = replace(self_p, None);
+ sender_terminate(p.unwrap())
+ }
+ }
+ }
+ }
+
+ impl<T:Send> send_packet<T> {
+ pub fn unwrap(&mut self) -> *const packet<T> {
+ replace(&mut self.p, None).unwrap()
+ }
+ }
+
+ pub fn send_packet<T:Send>(p: *const packet<T>) -> send_packet<T> {
+ send_packet {
+ p: Some(p)
+ }
+ }
+
+ pub struct recv_packet<T:Send> {
+ p: Option<*const packet<T>>,
+ }
+
+ impl<T:Send> Drop for recv_packet<T> {
+ fn drop(&mut self) {
+ unsafe {
+ if self.p != None {
+ let self_p: &mut Option<*const packet<T>> =
+ mem::transmute(&mut self.p);
+ let p = replace(self_p, None);
+ receiver_terminate(p.unwrap())
+ }
+ }
+ }
+ }
+
+ impl<T:Send> recv_packet<T> {
+ pub fn unwrap(&mut self) -> *const packet<T> {
+ replace(&mut self.p, None).unwrap()
+ }
+ }
+
+ pub fn recv_packet<T:Send>(p: *const packet<T>) -> recv_packet<T> {
+ recv_packet {
+ p: Some(p)
+ }
+ }
+
+ pub fn entangle<T:Send>() -> (send_packet<T>, recv_packet<T>) {
+ let p = packet();
+ (send_packet(p), recv_packet(p))
+ }
+}
+
+pub mod pingpong {
+ use std::mem;
+
+ pub struct ping(::pipes::send_packet<pong>);
+
+ unsafe impl Send for ping {}
+
+ pub struct pong(::pipes::send_packet<ping>);
+
+ unsafe impl Send for pong {}
+
+ pub fn liberate_ping(p: ping) -> ::pipes::send_packet<pong> {
+ unsafe {
+ let _addr : *const ::pipes::send_packet<pong> = match &p {
+ &ping(ref x) => { mem::transmute(x) }
+ };
+ panic!()
+ }
+ }
+
+ pub fn liberate_pong(p: pong) -> ::pipes::send_packet<ping> {
+ unsafe {
+ let _addr : *const ::pipes::send_packet<ping> = match &p {
+ &pong(ref x) => { mem::transmute(x) }
+ };
+ panic!()
+ }
+ }
+
+ pub fn init() -> (client::ping, server::ping) {
+ ::pipes::entangle()
+ }
+
+ pub mod client {
+ use pingpong;
+
+ pub type ping = ::pipes::send_packet<pingpong::ping>;
+ pub type pong = ::pipes::recv_packet<pingpong::pong>;
+
+ pub fn do_ping(c: ping) -> pong {
+ let (sp, rp) = ::pipes::entangle();
+
+ ::pipes::send(c, pingpong::ping(sp));
+ rp
+ }
+
+ pub fn do_pong(c: pong) -> (ping, ()) {
+ let packet = ::pipes::recv(c);
+ if packet.is_none() {
+ panic!("sender closed the connection")
+ }
+ (pingpong::liberate_pong(packet.unwrap()), ())
+ }
+ }
+
+ pub mod server {
+ use pingpong;
+
+ pub type ping = ::pipes::recv_packet<pingpong::ping>;
+ pub type pong = ::pipes::send_packet<pingpong::pong>;
+
+ pub fn do_ping(c: ping) -> (pong, ()) {
+ let packet = ::pipes::recv(c);
+ if packet.is_none() {
+ panic!("sender closed the connection")
+ }
+ (pingpong::liberate_ping(packet.unwrap()), ())
+ }
+
+ pub fn do_pong(c: pong) -> ping {
+ let (sp, rp) = ::pipes::entangle();
+ ::pipes::send(c, pingpong::pong(sp));
+ rp
+ }
+ }
+}
+
+fn client(chan: pingpong::client::ping) {
+ let chan = pingpong::client::do_ping(chan);
+ println!("Sent ping");
+ let (_chan, _data) = pingpong::client::do_pong(chan);
+ println!("Received pong");
+}
+
+fn server(chan: pingpong::server::ping) {
+ let (chan, _data) = pingpong::server::do_ping(chan);
+ println!("Received ping");
+ let _chan = pingpong::server::do_pong(chan);
+ println!("Sent pong");
+}
+
+pub fn main() {
+ /*
+// Commented out because of option::get error
+
+ let (client_, server_) = pingpong::init();
+
+ task::spawn {|client_|
+ let client__ = client_.take();
+ client(client__);
+ };
+ task::spawn {|server_|
+ let server__ = server_.take();
+ server(server_ËŠ);
+ };
+ */
+}
diff --git a/src/test/ui/regions/issue-28848.rs b/src/test/ui/regions/issue-28848.rs
new file mode 100644
index 000000000..0eb3d89c5
--- /dev/null
+++ b/src/test/ui/regions/issue-28848.rs
@@ -0,0 +1,14 @@
+struct Foo<'a, 'b: 'a>(&'a &'b ());
+
+impl<'a, 'b> Foo<'a, 'b> {
+ fn xmute(a: &'b ()) -> &'a () {
+ unreachable!()
+ }
+}
+
+pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+ Foo::<'a, 'b>::xmute(u)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-28848.stderr b/src/test/ui/regions/issue-28848.stderr
new file mode 100644
index 000000000..a29dac4c9
--- /dev/null
+++ b/src/test/ui/regions/issue-28848.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-28848.rs:10:5
+ |
+LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | Foo::<'a, 'b>::xmute(u)
+ | ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/issue-5243.rs b/src/test/ui/regions/issue-5243.rs
new file mode 100644
index 000000000..c511d45f0
--- /dev/null
+++ b/src/test/ui/regions/issue-5243.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(dead_code)]
+// Check that merely having lifetime parameters is not
+// enough for codegen to consider this as non-monomorphic,
+// which led to various assertions and failures in turn.
+
+// pretty-expanded FIXME #23616
+
+struct S<'a> {
+ v: &'a isize
+}
+
+fn f<'lt>(_s: &'lt S<'lt>) {}
+
+pub fn main() {
+ f(& S { v: &42 });
+}
diff --git a/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
new file mode 100644
index 000000000..bdd1ae91f
--- /dev/null
+++ b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
@@ -0,0 +1,67 @@
+// This is a collection of examples where a function's formal
+// parameter has an explicit lifetime and a closure within that
+// function returns that formal parameter. The closure's return type,
+// to be correctly inferred, needs to include the lifetime introduced
+// by the function.
+//
+// This works today, which precludes changing things so that closures
+// follow the same lifetime-elision rules used elsehwere. See
+// rust-lang/rust#56537
+
+// check-pass
+
+fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str {
+ let free_dumb = |_x| { p }; // no type annotation at all
+ let hello = format!("Hello");
+ free_dumb(&hello)
+}
+
+fn willy_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str {
+ let free_dumb = |_x| -> &str { p }; // type annotation on the return type
+ let hello = format!("Hello");
+ free_dumb(&hello)
+}
+
+fn willy_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str {
+ let free_dumb = |_x| -> &'w str { p }; // type+region annotation on return type
+ let hello = format!("Hello");
+ free_dumb(&hello)
+}
+
+fn willy_arg_type_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str {
+ let free_dumb = |_x: &str| -> &str { p }; // type annotation on arg and return types
+ let hello = format!("Hello");
+ free_dumb(&hello)
+}
+
+fn willy_arg_type_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str {
+ let free_dumb = |_x: &str| -> &'w str { p }; // fully annotated
+ let hello = format!("Hello");
+ free_dumb(&hello)
+}
+
+fn main() {
+ let world = format!("World");
+ let w1: &str = {
+ let hello = format!("He11o");
+ willy_no_annot(&world, &hello)
+ };
+ let w2: &str = {
+ let hello = format!("He22o");
+ willy_ret_type_annot(&world, &hello)
+ };
+ let w3: &str = {
+ let hello = format!("He33o");
+ willy_ret_region_annot(&world, &hello)
+ };
+ let w4: &str = {
+ let hello = format!("He44o");
+ willy_arg_type_ret_type_annot(&world, &hello)
+ };
+ let w5: &str = {
+ let hello = format!("He55o");
+ willy_arg_type_ret_region_annot(&world, &hello)
+ };
+ assert_eq!((w1, w2, w3, w4, w5),
+ ("World","World","World","World","World"));
+}
diff --git a/src/test/ui/regions/issue-6157.rs b/src/test/ui/regions/issue-6157.rs
new file mode 100644
index 000000000..b7a44ed86
--- /dev/null
+++ b/src/test/ui/regions/issue-6157.rs
@@ -0,0 +1,23 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub trait OpInt { fn call(&mut self, _: isize, _: isize) -> isize; }
+
+impl<F> OpInt for F where F: FnMut(isize, isize) -> isize {
+ fn call(&mut self, a:isize, b:isize) -> isize {
+ (*self)(a, b)
+ }
+}
+
+fn squarei<'a>(x: isize, op: &'a mut dyn OpInt) -> isize { op.call(x, x) }
+
+fn muli(x:isize, y:isize) -> isize { x * y }
+
+pub fn main() {
+ let mut f = |x, y| muli(x, y);
+ {
+ let g = &mut f;
+ let h = g as &mut dyn OpInt;
+ squarei(3, h);
+ }
+}
diff --git a/src/test/ui/regions/issue-72051-member-region-hang.rs b/src/test/ui/regions/issue-72051-member-region-hang.rs
new file mode 100644
index 000000000..b7340b79d
--- /dev/null
+++ b/src/test/ui/regions/issue-72051-member-region-hang.rs
@@ -0,0 +1,7 @@
+// Regression test for #72051, hang when resolving regions.
+
+// check-pass
+// edition:2018
+
+pub async fn query<'a>(_: &(), _: &(), _: (&(dyn std::any::Any + 'a),) ) {}
+fn main() {}
diff --git a/src/test/ui/regions/issue-78262.base.stderr b/src/test/ui/regions/issue-78262.base.stderr
new file mode 100644
index 000000000..7f232e4a7
--- /dev/null
+++ b/src/test/ui/regions/issue-78262.base.stderr
@@ -0,0 +1,14 @@
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/issue-78262.rs:12:26
+ |
+LL | let f = |x: &dyn TT| x.func();
+ | - - ^^^^^^^^
+ | | | |
+ | | | `x` escapes the closure body here
+ | | | argument requires that `'1` must outlive `'static`
+ | | let's call the lifetime of this reference `'1`
+ | `x` is a reference that is only valid in the closure body
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/regions/issue-78262.polonius.stderr b/src/test/ui/regions/issue-78262.polonius.stderr
new file mode 100644
index 000000000..7f232e4a7
--- /dev/null
+++ b/src/test/ui/regions/issue-78262.polonius.stderr
@@ -0,0 +1,14 @@
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/issue-78262.rs:12:26
+ |
+LL | let f = |x: &dyn TT| x.func();
+ | - - ^^^^^^^^
+ | | | |
+ | | | `x` escapes the closure body here
+ | | | argument requires that `'1` must outlive `'static`
+ | | let's call the lifetime of this reference `'1`
+ | `x` is a reference that is only valid in the closure body
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/regions/issue-78262.rs b/src/test/ui/regions/issue-78262.rs
new file mode 100644
index 000000000..642dbd7f8
--- /dev/null
+++ b/src/test/ui/regions/issue-78262.rs
@@ -0,0 +1,15 @@
+// revisions: base polonius
+// ignore-compare-mode-polonius
+// [polonius] compile-flags: -Z polonius
+
+trait TT {}
+
+impl dyn TT {
+ fn func(&self) {}
+}
+
+fn main() {
+ let f = |x: &dyn TT| x.func();
+ //[base]~^ ERROR: borrowed data escapes outside of closure
+ //[polonius]~^^ ERROR: borrowed data escapes outside of closure
+}
diff --git a/src/test/ui/regions/owned-implies-static.rs b/src/test/ui/regions/owned-implies-static.rs
new file mode 100644
index 000000000..2efa8cc02
--- /dev/null
+++ b/src/test/ui/regions/owned-implies-static.rs
@@ -0,0 +1,8 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+fn f<T: 'static>(_x: T) {}
+
+pub fn main() {
+ f(Box::new(5));
+}
diff --git a/src/test/ui/regions/rcvr-borrowed-to-region.rs b/src/test/ui/regions/rcvr-borrowed-to-region.rs
new file mode 100644
index 000000000..7f32b8b91
--- /dev/null
+++ b/src/test/ui/regions/rcvr-borrowed-to-region.rs
@@ -0,0 +1,28 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+
+trait get {
+ fn get(self) -> isize;
+}
+
+// Note: impl on a slice; we're checking that the pointers below
+// correctly get borrowed to `&`. (similar to impling for `isize`, with
+// `&self` instead of `self`.)
+impl<'a> get for &'a isize {
+ fn get(self) -> isize {
+ return *self;
+ }
+}
+
+pub fn main() {
+ let x: Box<_> = 6.into();
+ let y = x.get();
+ println!("y={}", y);
+ assert_eq!(y, 6);
+
+ let x = &6;
+ let y = x.get();
+ println!("y={}", y);
+ assert_eq!(y, 6);
+}
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-big.rs b/src/test/ui/regions/region-borrow-params-issue-29793-big.rs
new file mode 100644
index 000000000..83b1a6eab
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-big.rs
@@ -0,0 +1,74 @@
+// Issue #29793, big regression test: do not let borrows of
+// parameters to ever be returned (expanded with exploration of
+// variations).
+//
+// This is the version of the test that actually exposed unsound
+// behavior (because the improperly accepted closure was actually
+// able to be invoked).
+
+struct WrapA<F>(Option<F>);
+
+impl<F> WrapA<F> {
+ fn new() -> WrapA<F> {
+ WrapA(None)
+ }
+ fn set(mut self, f: F) -> Self {
+ self.0 = Some(f);
+ self
+ }
+}
+
+struct WrapB<F>(Option<F>);
+
+impl<F> WrapB<F> {
+ fn new() -> WrapB<F> {
+ WrapB(None)
+ }
+ fn set(mut self, f: F) -> Self {
+ self.0 = Some(f);
+ self
+ }
+}
+
+trait DoStuff : Sized {
+ fn handle(self);
+}
+
+impl<F, T> DoStuff for WrapA<F>
+ where F: FnMut(usize, usize) -> T, T: DoStuff {
+ fn handle(mut self) {
+ if let Some(ref mut f) = self.0 {
+ let x = f(1, 2);
+ let _foo = [0usize; 16];
+ x.handle();
+ }
+ }
+ }
+
+impl<F> DoStuff for WrapB<F> where F: FnMut(bool) -> usize {
+ fn handle(mut self) {
+ if let Some(ref mut f) = self.0 {
+ println!("{}", f(true));
+ }
+ }
+}
+
+impl<F, T> WrapA<F>
+ where F: FnMut(usize, usize) -> T, T: DoStuff {
+ fn handle_ref(&mut self) {
+ if let Some(ref mut f) = self.0 {
+ let x = f(1, 2);
+ }
+ }
+ }
+
+fn main() {
+ let mut w = WrapA::new().set(|x: usize, y: usize| {
+ WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ //~^ ERROR closure may outlive the current function
+ //~| ERROR closure may outlive the current function
+ });
+
+ w.handle(); // This works
+ // w.handle_ref(); // This doesn't
+}
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-big.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-big.stderr
new file mode 100644
index 000000000..561dd64b4
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-big.stderr
@@ -0,0 +1,39 @@
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-big.rs:67:26
+ |
+LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-big.rs:67:9
+ |
+LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-big.rs:67:26
+ |
+LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-big.rs:67:9
+ |
+LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-small.rs b/src/test/ui/regions/region-borrow-params-issue-29793-small.rs
new file mode 100644
index 000000000..5f1c2ed08
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-small.rs
@@ -0,0 +1,212 @@
+// Issue #29793, small regression tests: do not let borrows of
+// parameters to ever be returned (expanded with exploration of
+// variations).
+
+// CLOSURES
+
+fn escaping_borrow_of_closure_params_1() {
+ let g = |x: usize, y:usize| {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ return f;
+ };
+
+ // We delberately do not call `g`; this small version of the test,
+ // after adding such a call, was (properly) rejected even when the
+ // system still suffered from issue #29793.
+
+ // g(10, 20)(true);
+}
+
+fn escaping_borrow_of_closure_params_2() {
+ let g = |x: usize, y:usize| {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ f
+ };
+
+ // (we don't call `g`; see above)
+}
+
+fn move_of_closure_params() {
+ let g = |x: usize, y:usize| {
+ let f = move |t: bool| if t { x } else { y };
+ f;
+ };
+ // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+ (g(1,2));
+}
+
+fn ok_borrow_of_fn_params(a: usize, b:usize) {
+ let g = |x: usize, y:usize| {
+ let f = |t: bool| if t { a } else { b };
+ return f;
+ };
+ // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+ (g(1,2))(true);
+}
+
+// TOP-LEVEL FN'S
+
+fn escaping_borrow_of_fn_params_1() {
+ fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ return Box::new(f);
+ };
+
+ // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_fn_params_2() {
+ fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ Box::new(f)
+ };
+
+ // (we don't call `g`; see above)
+}
+
+fn move_of_fn_params() {
+ fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = move |t: bool| if t { x } else { y };
+ return Box::new(f);
+ };
+ // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+ (g(1,2))(true);
+}
+
+// INHERENT METHODS
+
+fn escaping_borrow_of_method_params_1() {
+ struct S;
+ impl S {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ return Box::new(f);
+ }
+ }
+
+ // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_method_params_2() {
+ struct S;
+ impl S {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ Box::new(f)
+ }
+ }
+ // (we don't call `g`; see above)
+}
+
+fn move_of_method_params() {
+ struct S;
+ impl S {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = move |t: bool| if t { x } else { y };
+ return Box::new(f);
+ }
+ }
+ // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+ (S.g(1,2))(true);
+}
+
+// TRAIT IMPL METHODS
+
+fn escaping_borrow_of_trait_impl_params_1() {
+ trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; }
+ struct S;
+ impl T for S {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ return Box::new(f);
+ }
+ }
+
+ // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_trait_impl_params_2() {
+ trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; }
+ struct S;
+ impl T for S {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ Box::new(f)
+ }
+ }
+ // (we don't call `g`; see above)
+}
+
+fn move_of_trait_impl_params() {
+ trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; }
+ struct S;
+ impl T for S {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = move |t: bool| if t { x } else { y };
+ return Box::new(f);
+ }
+ }
+ // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+ (S.g(1,2))(true);
+}
+
+// TRAIT DEFAULT METHODS
+
+fn escaping_borrow_of_trait_default_params_1() {
+ struct S;
+ trait T {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ return Box::new(f);
+ }
+ }
+ impl T for S {}
+ // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_trait_default_params_2() {
+ struct S;
+ trait T {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ //~^ ERROR E0373
+ //~| ERROR E0373
+ Box::new(f)
+ }
+ }
+ impl T for S {}
+ // (we don't call `g`; see above)
+}
+
+fn move_of_trait_default_params() {
+ struct S;
+ trait T {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
+ let f = move |t: bool| if t { x } else { y };
+ return Box::new(f);
+ }
+ }
+ impl T for S {}
+ // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+ (S.g(1,2))(true);
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-small.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-small.stderr
new file mode 100644
index 000000000..e446f2a00
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-small.stderr
@@ -0,0 +1,363 @@
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:9:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:12:16
+ |
+LL | return f;
+ | ^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:9:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:12:16
+ |
+LL | return f;
+ | ^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:24:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:27:9
+ |
+LL | f
+ | ^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:24:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:27:9
+ |
+LL | f
+ | ^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:55:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:58:16
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:55:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:58:16
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:66:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:69:9
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:66:17
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:69:9
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:90:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:93:20
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:90:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:93:20
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:104:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:107:13
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:104:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:107:13
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:132:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:135:20
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:132:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:135:20
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:147:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:150:13
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:147:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:150:13
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:175:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:178:20
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:175:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:178:20
+ |
+LL | return Box::new(f);
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:189:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:192:13
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+ --> $DIR/region-borrow-params-issue-29793-small.rs:189:21
+ |
+LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ^^^^^^^^^ - `y` is borrowed here
+ | |
+ | may outlive borrowed value `y`
+ |
+note: closure is returned here
+ --> $DIR/region-borrow-params-issue-29793-small.rs:192:13
+ |
+LL | Box::new(f)
+ | ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+ |
+LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+ | ++++
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
new file mode 100644
index 000000000..72d82da45
--- /dev/null
+++ b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
@@ -0,0 +1,16 @@
+// Test related to #22779. In this case, the impl is an inherent impl,
+// so it doesn't have to match any trait, so no error results.
+
+// check-pass
+#![allow(dead_code)]
+
+struct MySlice<'a, T:'a>(&'a mut [T]);
+
+impl<'a, T> MySlice<'a, T> {
+ fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
+ &mut self.0[..]
+ }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.rs b/src/test/ui/regions/region-bound-on-closure-outlives-call.rs
new file mode 100644
index 000000000..1311d5121
--- /dev/null
+++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.rs
@@ -0,0 +1,6 @@
+fn call_rec<F>(mut f: F) -> usize where F: FnMut(usize) -> usize {
+ //~^ WARN function cannot return without recursing
+ (|x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr b/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
new file mode 100644
index 000000000..a2396ad42
--- /dev/null
+++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
@@ -0,0 +1,24 @@
+warning: function cannot return without recursing
+ --> $DIR/region-bound-on-closure-outlives-call.rs:1:1
+ |
+LL | fn call_rec<F>(mut f: F) -> usize where F: FnMut(usize) -> usize {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL | (|x| f(x))(call_rec(f))
+ | ----------- recursive call site
+ |
+ = note: `#[warn(unconditional_recursion)]` on by default
+ = help: a `loop` may express intention better if this is on purpose
+
+error[E0505]: cannot move out of `f` because it is borrowed
+ --> $DIR/region-bound-on-closure-outlives-call.rs:3:25
+ |
+LL | (|x| f(x))(call_rec(f))
+ | --- - ^ move out of `f` occurs here
+ | | |
+ | | borrow occurs due to use in closure
+ | borrow of `f` occurs here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
new file mode 100644
index 000000000..68056370c
--- /dev/null
+++ b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
@@ -0,0 +1,17 @@
+// Test related to #22779, but where the `'a:'b` relation
+// appears in the trait too. No error here.
+
+// check-pass
+
+trait Tr<'a, T> {
+ fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b;
+}
+
+impl<'a, T> Tr<'a, T> for &'a mut [T] {
+ fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
+ &mut self[..]
+ }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs
new file mode 100644
index 000000000..40d2b740b
--- /dev/null
+++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs
@@ -0,0 +1,36 @@
+// Test related to when a region bound is required to be specified.
+
+trait IsStatic : 'static { }
+trait IsSend : Send { }
+trait Is<'a> : 'a { }
+trait Is2<'a> : 'a { }
+trait SomeTrait { }
+
+// Bounds on object types:
+
+struct Foo<'a,'b,'c> { //~ ERROR parameter `'c` is never used
+ // All of these are ok, because we can derive exactly one bound:
+ a: Box<dyn IsStatic>,
+ b: Box<dyn Is<'static>>,
+ c: Box<dyn Is<'a>>,
+ d: Box<dyn IsSend>,
+ e: Box<dyn Is<'a>+Send>, // we can derive two bounds, but one is 'static, so ok
+ f: Box<dyn SomeTrait>, // OK, defaults to 'static due to RFC 599.
+ g: Box<dyn SomeTrait+'a>,
+
+ z: Box<dyn Is<'a>+'b+'c>,
+ //~^ ERROR only a single explicit lifetime bound is permitted
+ //~| ERROR lifetime bound not satisfied
+}
+
+fn test<
+ 'a,
+ 'b,
+ A:IsStatic,
+ B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type.
+ C:'b+Is<'a>+Is2<'b>,
+ D:Is<'a>+Is2<'static>,
+ E:'a+'b // OK in a parameter, but not an object type.
+>() { }
+
+fn main() { }
diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
new file mode 100644
index 000000000..2ec2ca49b
--- /dev/null
+++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
@@ -0,0 +1,35 @@
+error[E0226]: only a single explicit lifetime bound is permitted
+ --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:26
+ |
+LL | z: Box<dyn Is<'a>+'b+'c>,
+ | ^^
+
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:8
+ |
+LL | z: Box<dyn Is<'a>+'b+'c>,
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lifetime parameter instantiated with the lifetime `'b` as defined here
+ --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15
+ |
+LL | struct Foo<'a,'b,'c> {
+ | ^^
+note: but lifetime parameter must outlive the lifetime `'a` as defined here
+ --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12
+ |
+LL | struct Foo<'a,'b,'c> {
+ | ^^
+
+error[E0392]: parameter `'c` is never used
+ --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18
+ |
+LL | struct Foo<'a,'b,'c> {
+ | ^^ unused parameter
+ |
+ = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0226, E0392, E0478.
+For more information about an error, try `rustc --explain E0226`.
diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.rs b/src/test/ui/regions/region-invariant-static-error-reporting.rs
new file mode 100644
index 000000000..c8288b592
--- /dev/null
+++ b/src/test/ui/regions/region-invariant-static-error-reporting.rs
@@ -0,0 +1,21 @@
+// This test checks that the error messages you get for this example
+// at least mention `'a` and `'static`. The precise messages can drift
+// over time, but this test used to exhibit some pretty bogus messages
+// that were not remotely helpful.
+
+// error-pattern:argument requires that `'a` must outlive `'static`
+
+struct Invariant<'a>(Option<&'a mut &'a mut ()>);
+
+fn mk_static() -> Invariant<'static> { Invariant(None) }
+
+fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
+ let bad = if x.is_some() {
+ x.unwrap() //~ ERROR borrowed data escapes outside of function [E0521]
+ } else {
+ mk_static()
+ };
+ f(bad);
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.stderr
new file mode 100644
index 000000000..2ad39b000
--- /dev/null
+++ b/src/test/ui/regions/region-invariant-static-error-reporting.stderr
@@ -0,0 +1,21 @@
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/region-invariant-static-error-reporting.rs:14:9
+ |
+LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
+ | -- - `x` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | let bad = if x.is_some() {
+LL | x.unwrap()
+ | ^^^^^^^^^^
+ | |
+ | `x` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+ |
+ = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs
new file mode 100644
index 000000000..d364c4677
--- /dev/null
+++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs
@@ -0,0 +1,30 @@
+fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a {
+ // Note: this is legal because of the `'b:'a` declaration.
+ *x = *y;
+}
+
+fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
+ // Illegal now because there is no `'b:'a` declaration.
+ *x = *y;
+}
+
+fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
+ // Here we try to call `foo` but do not know that `'a` and `'b` are
+ // related as required.
+ a(x, y);
+}
+
+fn d() {
+ // 'a and 'b are early bound in the function `a` because they appear
+ // inconstraints:
+ let _: fn(&mut &isize, &mut &isize) = a;
+ //~^ ERROR mismatched types [E0308]
+}
+
+fn e() {
+ // 'a and 'b are late bound in the function `b` because there are
+ // no constraints:
+ let _: fn(&mut &isize, &mut &isize) = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
new file mode 100644
index 000000000..48f2e1a2f
--- /dev/null
+++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43
+ |
+LL | let _: fn(&mut &isize, &mut &isize) = a;
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
+ found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs
new file mode 100644
index 000000000..60dafdd52
--- /dev/null
+++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs
@@ -0,0 +1,32 @@
+fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where 'b: 'a + 'c {
+ // Note: this is legal because of the `'b:'a` declaration.
+ *x = *y;
+ *z = *y;
+}
+
+fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+ // Illegal now because there is no `'b:'a` declaration.
+ *x = *y;
+ *z = *y;
+}
+
+fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+ // Here we try to call `foo` but do not know that `'a` and `'b` are
+ // related as required.
+ a(x, y, z);
+}
+
+fn d() {
+ // 'a and 'b are early bound in the function `a` because they appear
+ // inconstraints:
+ let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
+ //~^ ERROR E0308
+}
+
+fn e() {
+ // 'a and 'b are late bound in the function `b` because there are
+ // no constraints:
+ let _: fn(&mut &isize, &mut &isize, &mut &isize) = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
new file mode 100644
index 000000000..36f40cd9a
--- /dev/null
+++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56
+ |
+LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
+ found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/region-object-lifetime-1.rs b/src/test/ui/regions/region-object-lifetime-1.rs
new file mode 100644
index 000000000..ddf3be690
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-1.rs
@@ -0,0 +1,18 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+// check-pass
+#![allow(warnings)]
+
+trait Foo {
+ fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Here the receiver and return value all have the same lifetime,
+// so no error results.
+fn borrowed_receiver_same_lifetime<'a>(x: &'a Foo) -> &'a () {
+ x.borrowed()
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-2.rs b/src/test/ui/regions/region-object-lifetime-2.rs
new file mode 100644
index 000000000..cfdb8fefe
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-2.rs
@@ -0,0 +1,14 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+trait Foo {
+ fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Borrowed receiver but two distinct lifetimes, we get an error.
+fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
+ x.borrowed()
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr
new file mode 100644
index 000000000..d95289f3f
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-2.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-2.rs:10:5
+ |
+LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x.borrowed()
+ | ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/region-object-lifetime-3.rs b/src/test/ui/regions/region-object-lifetime-3.rs
new file mode 100644
index 000000000..0536fa2a2
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-3.rs
@@ -0,0 +1,18 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+// check-pass
+#![allow(warnings)]
+
+trait Foo {
+ fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Borrowed receiver with two distinct lifetimes, but we know that
+// 'b:'a, hence &'a () is permitted.
+fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
+ x.borrowed()
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-4.rs b/src/test/ui/regions/region-object-lifetime-4.rs
new file mode 100644
index 000000000..8f42df831
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-4.rs
@@ -0,0 +1,16 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+trait Foo {
+ fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Here we have two distinct lifetimes, but we try to return a pointer
+// with the longer lifetime when (from the signature) we only know
+// that it lives as long as the shorter lifetime. Therefore, error.
+fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
+ x.borrowed()
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-4.stderr b/src/test/ui/regions/region-object-lifetime-4.stderr
new file mode 100644
index 000000000..fda66a241
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-4.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-4.rs:12:5
+ |
+LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x.borrowed()
+ | ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/region-object-lifetime-5.rs b/src/test/ui/regions/region-object-lifetime-5.rs
new file mode 100644
index 000000000..ad3593671
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-5.rs
@@ -0,0 +1,14 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+trait Foo {
+ fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Here, the object is bounded by an anonymous lifetime and returned
+// as `&'static`, so you get an error.
+fn owned_receiver(x: Box<dyn Foo>) -> &'static () {
+ x.borrowed() //~ ERROR cannot return reference to local data `*x`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-5.stderr b/src/test/ui/regions/region-object-lifetime-5.stderr
new file mode 100644
index 000000000..b82b58c7a
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-5.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to local data `*x`
+ --> $DIR/region-object-lifetime-5.rs:11:5
+ |
+LL | x.borrowed()
+ | ^^^^^^^^^^^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
new file mode 100644
index 000000000..95708de04
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -0,0 +1,34 @@
+// Test that attempts to implicitly coerce a value into an
+// object respect the lifetime bound on the object type.
+
+trait Foo {}
+impl<'a> Foo for &'a [u8] {}
+
+fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
+ let x: Box<dyn Foo + 'static> = Box::new(v);
+ //~^ ERROR lifetime may not live long enough
+ x
+}
+
+fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
+ Box::new(v)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn c(v: &[u8]) -> Box<dyn Foo> {
+ // same as previous case due to RFC 599
+
+ Box::new(v)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
+ Box::new(v)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn e<'a:'b,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
+ Box::new(v) // OK, thanks to 'a:'b
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
new file mode 100644
index 000000000..b5bb08c73
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -0,0 +1,62 @@
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-in-coercion.rs:8:12
+ |
+LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
+ | - let's call the lifetime of this reference `'1`
+LL | let x: Box<dyn Foo + 'static> = Box::new(v);
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
+ |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+ |
+LL | fn a(v: &[u8]) -> Box<dyn Foo + '_> {
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn a(v: &'static [u8]) -> Box<dyn Foo + 'static> {
+ | ~~~~~~~~~~~~~
+
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+ |
+LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
+ | - let's call the lifetime of this reference `'1`
+LL | Box::new(v)
+ | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+ |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+ |
+LL | fn b(v: &[u8]) -> Box<dyn Foo + '_> {
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn b(v: &'static [u8]) -> Box<dyn Foo + 'static> {
+ | ~~~~~~~~~~~~~
+
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-in-coercion.rs:21:5
+ |
+LL | fn c(v: &[u8]) -> Box<dyn Foo> {
+ | - let's call the lifetime of this reference `'1`
+...
+LL | Box::new(v)
+ | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+ |
+help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn c(v: &[u8]) -> Box<dyn Foo + '_> {
+ | ++++
+
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-in-coercion.rs:26:5
+ |
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | Box::new(v)
+ | ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/regions/regions-addr-of-arg.rs b/src/test/ui/regions/regions-addr-of-arg.rs
new file mode 100644
index 000000000..1805141c4
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-arg.rs
@@ -0,0 +1,17 @@
+// Check that taking the address of an argument yields a lifetime
+// bounded by the current function call.
+
+fn foo(a: isize) {
+ let _p: &'static isize = &a; //~ ERROR `a` does not live long enough
+}
+
+fn bar(a: isize) {
+ let _q: &isize = &a;
+}
+
+fn zed<'a>(a: isize) -> &'a isize {
+ &a //~ ERROR cannot return reference to function parameter `a`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-addr-of-arg.stderr b/src/test/ui/regions/regions-addr-of-arg.stderr
new file mode 100644
index 000000000..e77289287
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-arg.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `a` does not live long enough
+ --> $DIR/regions-addr-of-arg.rs:5:30
+ |
+LL | let _p: &'static isize = &a;
+ | -------------- ^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `a` is borrowed for `'static`
+LL | }
+ | - `a` dropped here while still borrowed
+
+error[E0515]: cannot return reference to function parameter `a`
+ --> $DIR/regions-addr-of-arg.rs:13:5
+ |
+LL | &a
+ | ^^ returns a reference to data owned by the current function
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-addr-of-interior-of-unique-box.rs b/src/test/ui/regions/regions-addr-of-interior-of-unique-box.rs
new file mode 100644
index 000000000..4221ebfdf
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-interior-of-unique-box.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+
+// pretty-expanded FIXME #23616
+
+struct Point {
+ x: isize,
+ y: isize
+}
+
+struct Character {
+ pos: Box<Point>,
+}
+
+fn get_x(x: &Character) -> &isize {
+ // interesting case because the scope of this
+ // borrow of the unique pointer is in fact
+ // larger than the fn itself
+ return &x.pos.x;
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-addr-of-ret.rs b/src/test/ui/regions/regions-addr-of-ret.rs
new file mode 100644
index 000000000..e5dcd6db0
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-ret.rs
@@ -0,0 +1,9 @@
+// run-pass
+fn f(x: &isize) -> &isize {
+ return &*x;
+}
+
+pub fn main() {
+ let three = &3;
+ println!("{}", *f(three));
+}
diff --git a/src/test/ui/regions/regions-addr-of-self.rs b/src/test/ui/regions/regions-addr-of-self.rs
new file mode 100644
index 000000000..23647182f
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-self.rs
@@ -0,0 +1,28 @@
+struct Dog {
+ cats_chased: usize,
+}
+
+impl Dog {
+ pub fn chase_cat(&mut self) {
+ let p: &'static mut usize = &mut self.cats_chased;
+ //~^ ERROR lifetime may not live long enough
+ *p += 1;
+ }
+
+ pub fn chase_cat_2(&mut self) {
+ let p: &mut usize = &mut self.cats_chased;
+ *p += 1;
+ }
+}
+
+fn dog() -> Dog {
+ Dog {
+ cats_chased: 0
+ }
+}
+
+fn main() {
+ let mut d = dog();
+ d.chase_cat();
+ println!("cats_chased: {}", d.cats_chased);
+}
diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr
new file mode 100644
index 000000000..3d7aac74b
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-self.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-addr-of-self.rs:7:16
+ |
+LL | pub fn chase_cat(&mut self) {
+ | - let's call the lifetime of this reference `'1`
+LL | let p: &'static mut usize = &mut self.cats_chased;
+ | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.rs b/src/test/ui/regions/regions-addr-of-upvar-self.rs
new file mode 100644
index 000000000..171eca32e
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-upvar-self.rs
@@ -0,0 +1,18 @@
+struct Dog {
+ food: usize,
+}
+
+impl Dog {
+ pub fn chase_cat(&mut self) {
+ let _f = || {
+ let p: &'static mut usize = &mut self.food;
+ //~^ ERROR lifetime may not live long enough
+ //~^^ ERROR lifetime may not live long enough
+ //~^^^ ERROR E0597
+ *p = 3;
+ };
+ }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr
new file mode 100644
index 000000000..c16a6f858
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr
@@ -0,0 +1,35 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-addr-of-upvar-self.rs:8:20
+ |
+LL | let _f = || {
+ | -- lifetime `'1` represents this closure's body
+LL | let p: &'static mut usize = &mut self.food;
+ | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
+ |
+ = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+
+error: lifetime may not live long enough
+ --> $DIR/regions-addr-of-upvar-self.rs:8:20
+ |
+LL | pub fn chase_cat(&mut self) {
+ | - let's call the lifetime of this reference `'1`
+LL | let _f = || {
+LL | let p: &'static mut usize = &mut self.food;
+ | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
+
+error[E0597]: `self` does not live long enough
+ --> $DIR/regions-addr-of-upvar-self.rs:8:46
+ |
+LL | let _f = || {
+ | -- value captured here
+LL | let p: &'static mut usize = &mut self.food;
+ | ------------------ ^^^^^^^^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `self` is borrowed for `'static`
+...
+LL | }
+ | - `self` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-adjusted-lvalue-op.rs b/src/test/ui/regions/regions-adjusted-lvalue-op.rs
new file mode 100644
index 000000000..5aa5a3ecb
--- /dev/null
+++ b/src/test/ui/regions/regions-adjusted-lvalue-op.rs
@@ -0,0 +1,16 @@
+// check that we link regions in mutable place ops correctly - issue #41774
+
+struct Data(i32);
+
+trait OhNo {
+ fn oh_no(&mut self, other: &Vec<Data>) { loop {} }
+}
+
+impl OhNo for Data {}
+impl OhNo for [Data] {}
+
+fn main() {
+ let mut v = vec![Data(0)];
+ v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
+ (*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
+}
diff --git a/src/test/ui/regions/regions-adjusted-lvalue-op.stderr b/src/test/ui/regions/regions-adjusted-lvalue-op.stderr
new file mode 100644
index 000000000..2c5563444
--- /dev/null
+++ b/src/test/ui/regions/regions-adjusted-lvalue-op.stderr
@@ -0,0 +1,21 @@
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+ --> $DIR/regions-adjusted-lvalue-op.rs:14:16
+ |
+LL | v[0].oh_no(&v);
+ | - ----- ^^ immutable borrow occurs here
+ | | |
+ | | mutable borrow later used by call
+ | mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+ --> $DIR/regions-adjusted-lvalue-op.rs:15:16
+ |
+LL | (*v).oh_no(&v);
+ | - ----- ^^ immutable borrow occurs here
+ | | |
+ | | mutable borrow later used by call
+ | mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
new file mode 100644
index 000000000..eb6e66818
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
@@ -0,0 +1,41 @@
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears, even when the
+// associted type is in a supertype. Issue #22246.
+
+#![allow(dead_code)]
+
+pub trait TheTrait {
+ type TheAssocType;
+}
+
+pub trait TheSubTrait : TheTrait {
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+impl<'b> TheSubTrait for TheType<'b> {
+}
+
+pub struct WithAssoc<T:TheSubTrait> {
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a.
+
+ let _: &'a WithAssoc<TheType<'b>> = loop { };
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr
new file mode 100644
index 000000000..87e33e1cc
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:36:12
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs
new file mode 100644
index 000000000..575dfafe1
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs
@@ -0,0 +1,24 @@
+// Test that the compiler checks that arbitrary region bounds declared
+// in the trait must be satisfied on the impl. Issue #20890.
+
+trait Foo<'a> {
+ type Value: 'a;
+ fn dummy(&'a self) {}
+}
+
+impl<'a> Foo<'a> for &'a i16 {
+ // OK.
+ type Value = &'a i32;
+}
+
+impl<'a> Foo<'static> for &'a i32 {
+ type Value = &'a i32;
+ //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
+}
+
+impl<'a, 'b> Foo<'b> for &'a i64 {
+ type Value = &'a i32;
+ //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
new file mode 100644
index 000000000..ac6154139
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
@@ -0,0 +1,27 @@
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:18
+ |
+LL | type Value = &'a i32;
+ | ^^^^^^^
+ |
+note: type must satisfy the static lifetime as required by this binding
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:5:17
+ |
+LL | type Value: 'a;
+ | ^^
+
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:18
+ |
+LL | type Value = &'a i32;
+ | ^^^^^^^
+ |
+note: type must outlive the lifetime `'b` as defined here as required by this binding
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10
+ |
+LL | impl<'a, 'b> Foo<'b> for &'a i64 {
+ | ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound.rs b/src/test/ui/regions/regions-assoc-type-region-bound.rs
new file mode 100644
index 000000000..cbb7d1726
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-region-bound.rs
@@ -0,0 +1,22 @@
+// run-pass
+#![allow(dead_code)]
+// Test that the compiler considers the 'a bound declared in the
+// trait. Issue #20890.
+
+// pretty-expanded FIXME #23616
+
+trait Foo<'a> {
+ type Value: 'a;
+
+ fn get(&self) -> &'a Self::Value;
+}
+
+fn takes_foo<'a,F: Foo<'a>>(f: &'a F) {
+ // This call would be illegal, because it results in &'a F::Value,
+ // and the only way we know that `F::Value : 'a` is because of the
+ // trait declaration.
+
+ f.get();
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs
new file mode 100644
index 000000000..00100e0e9
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs
@@ -0,0 +1,19 @@
+// Test that the compiler checks that the 'static bound declared in
+// the trait must be satisfied on the impl. Issue #20890.
+
+trait Foo {
+ type Value: 'static;
+ fn dummy(&self) {}
+}
+
+impl<'a> Foo for &'a i32 {
+ type Value = &'a i32;
+ //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
+}
+
+impl<'a> Foo for i32 {
+ // OK.
+ type Value = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
new file mode 100644
index 000000000..a96f5612f
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
@@ -0,0 +1,15 @@
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+ --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:18
+ |
+LL | type Value = &'a i32;
+ | ^^^^^^^
+ |
+note: type must satisfy the static lifetime as required by this binding
+ --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:5:17
+ |
+LL | type Value: 'static;
+ | ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound.rs b/src/test/ui/regions/regions-assoc-type-static-bound.rs
new file mode 100644
index 000000000..1458787ea
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-static-bound.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(dead_code)]
+// Test that the compiler considers the 'static bound declared in the
+// trait. Issue #20890.
+
+// pretty-expanded FIXME #23616
+
+trait Foo {
+ type Value: 'static;
+ fn dummy(&self) { }
+}
+
+fn require_static<T: 'static>() {}
+
+fn takes_foo<F: Foo>() {
+ require_static::<F::Value>()
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-borrow-at.rs b/src/test/ui/regions/regions-borrow-at.rs
new file mode 100644
index 000000000..152abe109
--- /dev/null
+++ b/src/test/ui/regions/regions-borrow-at.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+fn foo(x: &usize) -> usize {
+ *x
+}
+
+pub fn main() {
+ let p: Box<_> = Box::new(22);
+ let r = foo(&*p);
+ println!("r={}", r);
+ assert_eq!(r, 22);
+}
diff --git a/src/test/ui/regions/regions-borrow-evec-fixed.rs b/src/test/ui/regions/regions-borrow-evec-fixed.rs
new file mode 100644
index 000000000..ed828312b
--- /dev/null
+++ b/src/test/ui/regions/regions-borrow-evec-fixed.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+fn foo(x: &[isize]) -> isize {
+ x[0]
+}
+
+pub fn main() {
+ let p = &[1,2,3,4,5];
+ assert_eq!(foo(p), 1);
+}
diff --git a/src/test/ui/regions/regions-borrow-evec-uniq.rs b/src/test/ui/regions/regions-borrow-evec-uniq.rs
new file mode 100644
index 000000000..bbf7ba79e
--- /dev/null
+++ b/src/test/ui/regions/regions-borrow-evec-uniq.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+
+fn foo(x: &[isize]) -> isize {
+ x[0]
+}
+
+pub fn main() {
+ let p = vec![1,2,3,4,5];
+ let r = foo(&p);
+ assert_eq!(r, 1);
+
+ let p = vec![5,4,3,2,1];
+ let r = foo(&p);
+ assert_eq!(r, 5);
+}
diff --git a/src/test/ui/regions/regions-borrow-uniq.rs b/src/test/ui/regions/regions-borrow-uniq.rs
new file mode 100644
index 000000000..adc6b1939
--- /dev/null
+++ b/src/test/ui/regions/regions-borrow-uniq.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+fn foo(x: &usize) -> usize {
+ *x
+}
+
+pub fn main() {
+ let p: Box<_> = Box::new(3);
+ let r = foo(&*p);
+ assert_eq!(r, 3);
+}
diff --git a/src/test/ui/regions/regions-bot.rs b/src/test/ui/regions/regions-bot.rs
new file mode 100644
index 000000000..580162936
--- /dev/null
+++ b/src/test/ui/regions/regions-bot.rs
@@ -0,0 +1,11 @@
+// run-pass
+#![allow(dead_code)]
+// A very limited test of the "bottom" region
+
+
+fn produce_static<T>() -> &'static T { panic!(); }
+
+fn foo<T>(_x: &T) -> &usize { produce_static() }
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-bound-lists-feature-gate-2.rs b/src/test/ui/regions/regions-bound-lists-feature-gate-2.rs
new file mode 100644
index 000000000..2c7503799
--- /dev/null
+++ b/src/test/ui/regions/regions-bound-lists-feature-gate-2.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(stable_features)]
+
+#![feature(issue_5723_bootstrap)]
+
+trait Foo {
+ fn dummy(&self) { }
+}
+
+fn foo<'a, 'b, 'c:'a+'b, 'd>() {
+}
+
+pub fn main() { }
diff --git a/src/test/ui/regions/regions-bound-lists-feature-gate.rs b/src/test/ui/regions/regions-bound-lists-feature-gate.rs
new file mode 100644
index 000000000..3815498f8
--- /dev/null
+++ b/src/test/ui/regions/regions-bound-lists-feature-gate.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(stable_features)]
+
+#![feature(issue_5723_bootstrap)]
+
+trait Foo {
+ fn dummy(&self) { }
+}
+
+fn foo<'a>(x: Box<dyn Foo + 'a>) {
+}
+
+fn bar<'a, T: 'a>() {
+}
+
+pub fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs
new file mode 100644
index 000000000..7d02a4619
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs
@@ -0,0 +1,69 @@
+// Test which of the builtin types are considered sendable. The tests
+// in this file all test region bound and lifetime violations that are
+// detected during type check.
+
+trait Dummy : 'static { }
+fn assert_send<T:'static>() { }
+
+// lifetime pointers with 'static lifetime are ok
+
+fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
+ assert_send::<&'static isize>();
+ assert_send::<&'static str>();
+ assert_send::<&'static [isize]>();
+
+ // whether or not they are mutable
+ assert_send::<&'static mut isize>();
+}
+
+// otherwise lifetime pointers are not ok
+
+fn param_not_ok<'a>(x: &'a isize) {
+ assert_send::<&'a isize>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn param_not_ok1<'a>(_: &'a isize) {
+ assert_send::<&'a str>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn param_not_ok2<'a>(_: &'a isize) {
+ assert_send::<&'a [isize]>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+// boxes are ok
+
+fn box_ok() {
+ assert_send::<Box<isize>>();
+ assert_send::<String>();
+ assert_send::<Vec<isize>>();
+}
+
+// but not if they own a bad thing
+
+fn box_with_region_not_ok<'a>() {
+ assert_send::<Box<&'a isize>>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+// raw pointers are ok unless they point at unsendable things
+
+fn unsafe_ok1<'a>(_: &'a isize) {
+ assert_send::<*const isize>();
+ assert_send::<*mut isize>();
+}
+
+fn unsafe_ok2<'a>(_: &'a isize) {
+ assert_send::<*const &'a isize>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn unsafe_ok3<'a>(_: &'a isize) {
+ assert_send::<*mut &'a isize>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr
new file mode 100644
index 000000000..eea68cc8f
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr
@@ -0,0 +1,50 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-by-trait-requiring-static.rs:22:5
+ |
+LL | fn param_not_ok<'a>(x: &'a isize) {
+ | -- lifetime `'a` defined here
+LL | assert_send::<&'a isize>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-by-trait-requiring-static.rs:27:5
+ |
+LL | fn param_not_ok1<'a>(_: &'a isize) {
+ | -- lifetime `'a` defined here
+LL | assert_send::<&'a str>();
+ | ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-by-trait-requiring-static.rs:32:5
+ |
+LL | fn param_not_ok2<'a>(_: &'a isize) {
+ | -- lifetime `'a` defined here
+LL | assert_send::<&'a [isize]>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-by-trait-requiring-static.rs:47:5
+ |
+LL | fn box_with_region_not_ok<'a>() {
+ | -- lifetime `'a` defined here
+LL | assert_send::<Box<&'a isize>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5
+ |
+LL | fn unsafe_ok2<'a>(_: &'a isize) {
+ | -- lifetime `'a` defined here
+LL | assert_send::<*const &'a isize>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-by-trait-requiring-static.rs:64:5
+ |
+LL | fn unsafe_ok3<'a>(_: &'a isize) {
+ | -- lifetime `'a` defined here
+LL | assert_send::<*mut &'a isize>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs
new file mode 100644
index 000000000..c014b2ccf
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs
@@ -0,0 +1,24 @@
+// aux-build:rbmtp_cross_crate_lib.rs
+
+// Check explicit region bounds on methods in the cross crate case.
+
+extern crate rbmtp_cross_crate_lib as lib;
+
+use lib::Inv;
+use lib::MaybeOwned;
+use lib::IntoMaybeOwned;
+
+fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) {
+ // Exercise a code path I found to be buggy. We were not encoding
+ // the region parameters from the receiver correctly on trait
+ // methods.
+ f.into_maybe_owned();
+}
+
+fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
+ // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
+ a.bigger_region(b)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr
new file mode 100644
index 000000000..6193bf02f
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:20:5
+ |
+LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
+ | -- -- lifetime `'y` defined here
+ | |
+ | lifetime `'x` defined here
+LL | // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
+LL | a.bigger_region(b)
+ | ^^^^^^^^^^^^^^^^^^ argument requires that `'y` must outlive `'x`
+ |
+ = help: consider adding the following bound: `'y: 'x`
+ = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Inv<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs
new file mode 100644
index 000000000..5548cb915
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs
@@ -0,0 +1,29 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Inv<'a> { // invariant w/r/t 'a
+ x: &'a mut &'a isize
+}
+
+trait Foo<'x> {
+ fn method<'y:'x>(self, y: Inv<'y>);
+}
+
+fn caller1<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+ // Here the value provided for 'y is 'a, and hence 'a:'a holds.
+ f.method(a);
+}
+
+fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+ // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
+ f.method(b);
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+ // Here the value provided for 'y is 'b, and hence 'b:'a holds.
+ f.method(b);
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr
new file mode 100644
index 000000000..0e0086be9
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5
+ |
+LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
+LL | f.method(b);
+ | ^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+ = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Inv<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.rs b/src/test/ui/regions/regions-bounded-method-type-parameters.rs
new file mode 100644
index 000000000..56e750003
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters.rs
@@ -0,0 +1,16 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Foo;
+
+impl Foo {
+ fn some_method<A:'static>(self) { }
+}
+
+fn caller<'a>(x: &isize) {
+ Foo.some_method::<&'a isize>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters.stderr
new file mode 100644
index 000000000..b6d7b8aac
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-bounded-method-type-parameters.rs:12:9
+ |
+LL | fn caller<'a>(x: &isize) {
+ | -- lifetime `'a` defined here
+LL | Foo.some_method::<&'a isize>();
+ | ^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-bounds.rs b/src/test/ui/regions/regions-bounds.rs
new file mode 100644
index 000000000..fd4d75ab6
--- /dev/null
+++ b/src/test/ui/regions/regions-bounds.rs
@@ -0,0 +1,18 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct TupleStruct<'a>(&'a isize);
+struct Struct<'a> { x:&'a isize }
+
+fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
+ return e;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
+ return e;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounds.stderr b/src/test/ui/regions/regions-bounds.stderr
new file mode 100644
index 000000000..430909e54
--- /dev/null
+++ b/src/test/ui/regions/regions-bounds.stderr
@@ -0,0 +1,26 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-bounds.rs:9:12
+ |
+LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | return e;
+ | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-bounds.rs:14:12
+ |
+LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | return e;
+ | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.rs b/src/test/ui/regions/regions-close-associated-type-into-object.rs
new file mode 100644
index 000000000..428477e24
--- /dev/null
+++ b/src/test/ui/regions/regions-close-associated-type-into-object.rs
@@ -0,0 +1,71 @@
+trait X {}
+
+
+
+trait Iter {
+ type Item: X;
+
+ fn into_item(self) -> Self::Item;
+ fn as_item(&self) -> &Self::Item;
+}
+
+fn bad1<T: Iter>(v: T) -> Box<dyn X + 'static>
+{
+ let item = v.into_item();
+ Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad2<T: Iter>(v: T) -> Box<dyn X + 'static>
+ where Box<T::Item> : X
+{
+ let item: Box<_> = Box::new(v.into_item());
+ Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad3<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
+{
+ let item = v.into_item();
+ Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad4<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
+ where Box<T::Item> : X
+{
+ let item: Box<_> = Box::new(v.into_item());
+ Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn ok1<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
+ where T::Item : 'a
+{
+ let item = v.into_item();
+ Box::new(item) // OK, T::Item : 'a is declared
+}
+
+fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box<dyn X + 'a>
+ where T::Item : Clone
+{
+ let item = Clone::clone(w);
+ Box::new(item) // OK, T::Item : 'a is implied
+}
+
+fn ok3<'a, T: Iter>(v: &'a T) -> Box<dyn X + 'a>
+ where T::Item : Clone + 'a
+{
+ let item = Clone::clone(v.as_item());
+ Box::new(item) // OK, T::Item : 'a was declared
+}
+
+fn meh1<'a, T: Iter>(v: &'a T) -> Box<dyn X + 'a>
+ where T::Item : Clone
+{
+ // This case is kind of interesting. It's the same as `ok3` but
+ // without the explicit declaration. This is valid because `T: 'a
+ // => T::Item: 'a`, and the former we can deduce from our argument
+ // of type `&'a T`.
+
+ let item = Clone::clone(v.as_item());
+ Box::new(item)
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.stderr b/src/test/ui/regions/regions-close-associated-type-into-object.stderr
new file mode 100644
index 000000000..f7dcaa9d9
--- /dev/null
+++ b/src/test/ui/regions/regions-close-associated-type-into-object.stderr
@@ -0,0 +1,40 @@
+error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
+ --> $DIR/regions-close-associated-type-into-object.rs:15:5
+ |
+LL | Box::new(item)
+ | ^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
+
+error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
+ --> $DIR/regions-close-associated-type-into-object.rs:22:5
+ |
+LL | Box::new(item)
+ | ^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
+
+error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
+ --> $DIR/regions-close-associated-type-into-object.rs:28:5
+ |
+LL | Box::new(item)
+ | ^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
+
+error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
+ --> $DIR/regions-close-associated-type-into-object.rs:35:5
+ |
+LL | Box::new(item)
+ | ^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-1.rs b/src/test/ui/regions/regions-close-object-into-object-1.rs
new file mode 100644
index 000000000..2dc33d567
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-1.rs
@@ -0,0 +1,15 @@
+#![allow(warnings)]
+
+trait A<T> { }
+
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { }
+
+impl<'a, T> X for B<'a, T> {}
+
+fn f<'a, T:'static, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+ Box::new(B(&*v)) as Box<X> //~ ERROR cannot return value referencing local data `*v`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-1.stderr b/src/test/ui/regions/regions-close-object-into-object-1.stderr
new file mode 100644
index 000000000..5bfaeb295
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-1.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*v`
+ --> $DIR/regions-close-object-into-object-1.rs:12:5
+ |
+LL | Box::new(B(&*v)) as Box<X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
+ | returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.rs b/src/test/ui/regions/regions-close-object-into-object-2.rs
new file mode 100644
index 000000000..6960af72c
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-2.rs
@@ -0,0 +1,14 @@
+trait A<T> { }
+
+struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
+
+trait X { }
+impl<'a, T> X for B<'a, T> {}
+
+fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
+ Box::new(B(&*v)) as Box<dyn X>
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR cannot return value referencing local data `*v` [E0515]
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
new file mode 100644
index 000000000..aacb5ea4e
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -0,0 +1,29 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-close-object-into-object-2.rs:9:5
+ |
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
+ | -- lifetime `'a` defined here
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+ |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+ |
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'a> {
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn g<'a, T: 'static>(v: Box<(dyn A<T> + 'static)>) -> Box<dyn X + 'static> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0515]: cannot return value referencing local data `*v`
+ --> $DIR/regions-close-object-into-object-2.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
+ | returns a value referencing data owned by the current function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-3.rs b/src/test/ui/regions/regions-close-object-into-object-3.rs
new file mode 100644
index 000000000..78d93b0ec
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-3.rs
@@ -0,0 +1,14 @@
+#![allow(warnings)]
+
+trait A<T> { }
+
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { }
+impl<'a, T> X for B<'a, T> {}
+
+fn h<'a, T, U:'static>(v: Box<A<U>+'static>) -> Box<X+'static> {
+ Box::new(B(&*v)) as Box<X> //~ ERROR cannot return value referencing local data `*v`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-3.stderr b/src/test/ui/regions/regions-close-object-into-object-3.stderr
new file mode 100644
index 000000000..9f92c40e1
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-3.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*v`
+ --> $DIR/regions-close-object-into-object-3.rs:11:5
+ |
+LL | Box::new(B(&*v)) as Box<X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
+ | returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.rs b/src/test/ui/regions/regions-close-object-into-object-4.rs
new file mode 100644
index 000000000..3bbad9cbf
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-4.rs
@@ -0,0 +1,19 @@
+trait A<T> { }
+
+struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
+
+trait X { }
+impl<'a, T> X for B<'a, T> {}
+
+fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ Box::new(B(&*v)) as Box<dyn X>
+ //~^ ERROR the parameter type `U` may not live long enough [E0310]
+ //~| ERROR the parameter type `U` may not live long enough [E0310]
+ //~| ERROR the parameter type `U` may not live long enough [E0310]
+ //~| ERROR lifetime may not live long enough
+ //~| ERROR cannot return value referencing local data `*v` [E0515]
+ //~| ERROR the parameter type `U` may not live long enough [E0310]
+
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
new file mode 100644
index 000000000..7a9f1ab00
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -0,0 +1,74 @@
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | +++++++++
+
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | +++++++++
+
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | +++++++++
+
+error: lifetime may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | -- lifetime `'a` defined here
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+ |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+ |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'a> {
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn i<'a, T, U>(v: Box<(dyn A<U> + 'static)>) -> Box<dyn X + 'static> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0515]: cannot return value referencing local data `*v`
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
+ | returns a value referencing data owned by the current function
+
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:14
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | +++++++++
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0310, E0515.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.rs b/src/test/ui/regions/regions-close-object-into-object-5.rs
new file mode 100644
index 000000000..d534c3749
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-5.rs
@@ -0,0 +1,25 @@
+#![allow(warnings)]
+
+
+trait A<T>
+{
+ fn get(&self) -> T { panic!() }
+}
+
+struct B<'a, T: 'a>(&'a (A<T> + 'a));
+
+trait X { fn foo(&self) {} }
+
+impl<'a, T> X for B<'a, T> {}
+
+fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ // oh dear!
+ Box::new(B(&*v)) as Box<dyn X>
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR cannot return value referencing local data `*v` [E0515]
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
new file mode 100644
index 000000000..311e8868c
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -0,0 +1,57 @@
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | +++++++++
+
+error[E0515]: cannot return value referencing local data `*v`
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
+ | returns a value referencing data owned by the current function
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:14
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | +++++++++
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0310, E0515.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.rs b/src/test/ui/regions/regions-close-over-type-parameter-1.rs
new file mode 100644
index 000000000..610f75745
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.rs
@@ -0,0 +1,24 @@
+// Test for what happens when a type parameter `A` is closed over into
+// an object. This should yield errors unless `A` (and the object)
+// both have suitable bounds.
+
+trait SomeTrait {
+ fn get(&self) -> isize;
+}
+
+
+fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
+ Box::new(v) as Box<dyn SomeTrait + 'static>
+ //~^ ERROR the parameter type `A` may not live long enough
+}
+
+fn make_object2<'a, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'a> {
+ Box::new(v) as Box<dyn SomeTrait + 'a>
+}
+
+fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
+ Box::new(v) as Box<dyn SomeTrait + 'b>
+ //~^ ERROR the parameter type `A` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
new file mode 100644
index 000000000..b7b557d7a
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
@@ -0,0 +1,26 @@
+error[E0310]: the parameter type `A` may not live long enough
+ --> $DIR/regions-close-over-type-parameter-1.rs:11:5
+ |
+LL | Box::new(v) as Box<dyn SomeTrait + 'static>
+ | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn make_object1<A: SomeTrait + 'static>(v: A) -> Box<dyn SomeTrait + 'static> {
+ | +++++++++
+
+error[E0309]: the parameter type `A` may not live long enough
+ --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+ |
+LL | Box::new(v) as Box<dyn SomeTrait + 'b>
+ | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn make_object3<'a, 'b, A: SomeTrait + 'a + 'b>(v: A) -> Box<dyn SomeTrait + 'b> {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs b/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs
new file mode 100644
index 000000000..e032a94c3
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs
@@ -0,0 +1,24 @@
+// Various tests where we over type parameters with multiple lifetime
+// bounds.
+
+trait SomeTrait { fn get(&self) -> isize; }
+
+
+fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'a> {
+ // A outlives 'a AND 'b...
+ Box::new(v) as Box<dyn SomeTrait + 'a> // ...hence this type is safe.
+}
+
+fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'b> {
+ // A outlives 'a AND 'b...
+ Box::new(v) as Box<dyn SomeTrait + 'b> // ...hence this type is safe.
+}
+
+fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
+ // A outlives 'a AND 'b...but not 'c.
+ Box::new(v) as Box<dyn SomeTrait + 'a>
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
new file mode 100644
index 000000000..baa0506d0
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-close-over-type-parameter-multiple.rs:19:5
+ |
+LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
+ | -- -- lifetime `'c` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // A outlives 'a AND 'b...but not 'c.
+LL | Box::new(v) as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'c`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs b/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs
new file mode 100644
index 000000000..48aad9481
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs
@@ -0,0 +1,21 @@
+// run-pass
+// A test where we (successfully) close over a reference into
+// an object.
+
+trait SomeTrait { fn get(&self) -> isize; }
+
+impl<'a> SomeTrait for &'a isize {
+ fn get(&self) -> isize {
+ **self
+ }
+}
+
+fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait+'a> {
+ Box::new(v) as Box<dyn SomeTrait+'a>
+}
+
+fn main() {
+ let i: isize = 22;
+ let obj = make_object(&i);
+ assert_eq!(22, obj.get());
+}
diff --git a/src/test/ui/regions/regions-close-param-into-object.rs b/src/test/ui/regions/regions-close-param-into-object.rs
new file mode 100644
index 000000000..2760e5eed
--- /dev/null
+++ b/src/test/ui/regions/regions-close-param-into-object.rs
@@ -0,0 +1,27 @@
+trait X { fn foo(&self) {} }
+
+fn p1<T>(v: T) -> Box<dyn X + 'static>
+ where T : X
+{
+ Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
+ where Box<T> : X
+{
+ Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
+ where T : X
+{
+ Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
+ where Box<T> : X
+{
+ Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr
new file mode 100644
index 000000000..9162be5b9
--- /dev/null
+++ b/src/test/ui/regions/regions-close-param-into-object.stderr
@@ -0,0 +1,48 @@
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-param-into-object.rs:6:5
+ |
+LL | Box::new(v)
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | where T : X + 'static
+ | +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-param-into-object.rs:12:5
+ |
+LL | Box::new(v)
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn p2<T: 'static>(v: Box<T>) -> Box<dyn X + 'static>
+ | +++++++++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-param-into-object.rs:18:5
+ |
+LL | Box::new(v)
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | where T : X + 'a
+ | ++++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-param-into-object.rs:24:5
+ |
+LL | Box::new(v)
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn p4<'a,T: 'a>(v: Box<T>) -> Box<dyn X + 'a>
+ | ++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-copy-closure.rs b/src/test/ui/regions/regions-copy-closure.rs
new file mode 100644
index 000000000..436400797
--- /dev/null
+++ b/src/test/ui/regions/regions-copy-closure.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+struct closure_box<'a> {
+ cl: Box<dyn FnMut() + 'a>,
+}
+
+fn box_it<'a>(x: Box<dyn FnMut() + 'a>) -> closure_box<'a> {
+ closure_box {cl: x}
+}
+
+pub fn main() {
+ let mut i = 3;
+ assert_eq!(i, 3);
+ {
+ let cl = || i += 1;
+ let mut cl_box = box_it(Box::new(cl));
+ (cl_box.cl)();
+ }
+ assert_eq!(i, 4);
+}
diff --git a/src/test/ui/regions/regions-creating-enums.rs b/src/test/ui/regions/regions-creating-enums.rs
new file mode 100644
index 000000000..6ed68f803
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums.rs
@@ -0,0 +1,33 @@
+enum Ast<'a> {
+ Num(usize),
+ Add(&'a Ast<'a>, &'a Ast<'a>)
+}
+
+fn build() {
+ let x = Ast::Num(3);
+ let y = Ast::Num(4);
+ let z = Ast::Add(&x, &y);
+ compute(&z);
+}
+
+fn compute(x: &Ast) -> usize {
+ match *x {
+ Ast::Num(x) => { x }
+ Ast::Add(x, y) => { compute(x) + compute(y) }
+ }
+}
+
+fn map_nums<'a,'b, F>(x: &Ast, f: &mut F) -> &'a Ast<'b> where F: FnMut(usize) -> usize {
+ match *x {
+ Ast::Num(x) => {
+ return &Ast::Num((*f)(x)); //~ ERROR cannot return reference to temporary value
+ }
+ Ast::Add(x, y) => {
+ let m_x = map_nums(x, f);
+ let m_y = map_nums(y, f);
+ return &Ast::Add(m_x, m_y); //~ ERROR cannot return reference to temporary value
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-creating-enums.stderr b/src/test/ui/regions/regions-creating-enums.stderr
new file mode 100644
index 000000000..a95d84629
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums.stderr
@@ -0,0 +1,21 @@
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/regions-creating-enums.rs:23:16
+ |
+LL | return &Ast::Num((*f)(x));
+ | ^-----------------
+ | ||
+ | |temporary value created here
+ | returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/regions-creating-enums.rs:28:16
+ |
+LL | return &Ast::Add(m_x, m_y);
+ | ^------------------
+ | ||
+ | |temporary value created here
+ | returns a reference to data owned by the current function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-creating-enums2.rs b/src/test/ui/regions/regions-creating-enums2.rs
new file mode 100644
index 000000000..7b16fb1a8
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums2.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+enum ast<'a> {
+ num(usize),
+ add(&'a ast<'a>, &'a ast<'a>)
+}
+
+fn mk_add_ok<'r>(x: &'r ast<'r>, y: &'r ast<'r>) -> ast<'r> {
+ ast::add(x, y)
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-creating-enums3.rs b/src/test/ui/regions/regions-creating-enums3.rs
new file mode 100644
index 000000000..39dbb3d8a
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums3.rs
@@ -0,0 +1,12 @@
+enum Ast<'a> {
+ Num(usize),
+ Add(&'a Ast<'a>, &'a Ast<'a>)
+}
+
+fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> {
+ Ast::Add(x, y)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-creating-enums3.stderr b/src/test/ui/regions/regions-creating-enums3.stderr
new file mode 100644
index 000000000..41d609b56
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums3.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-creating-enums3.rs:7:5
+ |
+LL | fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | Ast::Add(x, y)
+ | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-creating-enums4.rs b/src/test/ui/regions/regions-creating-enums4.rs
new file mode 100644
index 000000000..c9eab08cb
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums4.rs
@@ -0,0 +1,12 @@
+enum Ast<'a> {
+ Num(usize),
+ Add(&'a Ast<'a>, &'a Ast<'a>)
+}
+
+fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
+ Ast::Add(x, y)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr
new file mode 100644
index 000000000..91cf57e09
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums4.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-creating-enums4.rs:7:5
+ |
+LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | Ast::Add(x, y)
+ | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-creating-enums5.rs b/src/test/ui/regions/regions-creating-enums5.rs
new file mode 100644
index 000000000..ad3d9748b
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums5.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+enum ast<'a> {
+ num(usize),
+ add(&'a ast<'a>, &'a ast<'a>)
+}
+
+fn mk_add_ok<'a>(x: &'a ast<'a>, y: &'a ast<'a>, _z: &ast) -> ast<'a> {
+ ast::add(x, y)
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-debruijn-of-object.rs b/src/test/ui/regions/regions-debruijn-of-object.rs
new file mode 100644
index 000000000..0b5510489
--- /dev/null
+++ b/src/test/ui/regions/regions-debruijn-of-object.rs
@@ -0,0 +1,22 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+struct ctxt<'tcx> {
+ x: &'tcx i32
+}
+
+trait AstConv<'tcx> {
+ fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>;
+}
+
+fn foo(conv: &dyn AstConv) { }
+
+fn bar<'tcx>(conv: &dyn AstConv<'tcx>) {
+ foo(conv)
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-dependent-addr-of.rs b/src/test/ui/regions/regions-dependent-addr-of.rs
new file mode 100644
index 000000000..a6cb56e31
--- /dev/null
+++ b/src/test/ui/regions/regions-dependent-addr-of.rs
@@ -0,0 +1,112 @@
+// run-pass
+// Test lifetimes are linked properly when we create dependent region pointers.
+// Issue #3148.
+
+#![feature(box_patterns)]
+
+struct A {
+ value: B
+}
+
+struct B {
+ v1: isize,
+ v2: [isize; 3],
+ v3: Vec<isize> ,
+ v4: C,
+ v5: Box<C>,
+ v6: Option<C>
+}
+
+#[derive(Copy, Clone)]
+struct C {
+ f: isize
+}
+
+fn get_v1(a: &A) -> &isize {
+ // Region inferencer must deduce that &v < L2 < L1
+ let foo = &a.value; // L1
+ &foo.v1 // L2
+}
+
+fn get_v2(a: &A, i: usize) -> &isize {
+ let foo = &a.value;
+ &foo.v2[i]
+}
+
+fn get_v3(a: &A, i: usize) -> &isize {
+ let foo = &a.value;
+ &foo.v3[i]
+}
+
+fn get_v4(a: &A, _i: usize) -> &isize {
+ let foo = &a.value;
+ &foo.v4.f
+}
+
+fn get_v5(a: &A, _i: usize) -> &isize {
+ let foo = &a.value;
+ &foo.v5.f
+}
+
+fn get_v6_a(a: &A, _i: usize) -> &isize {
+ match a.value.v6 {
+ Some(ref v) => &v.f,
+ None => panic!()
+ }
+}
+
+fn get_v6_b(a: &A, _i: usize) -> &isize {
+ match *a {
+ A { value: B { v6: Some(ref v), .. } } => &v.f,
+ _ => panic!()
+ }
+}
+
+fn get_v6_c(a: &A, _i: usize) -> &isize {
+ match a {
+ &A { value: B { v6: Some(ref v), .. } } => &v.f,
+ _ => panic!()
+ }
+}
+
+fn get_v5_ref(a: &A, _i: usize) -> &isize {
+ match &a.value {
+ &B {v5: box C {f: ref v}, ..} => v
+ }
+}
+
+pub fn main() {
+ let a = A {value: B {v1: 22,
+ v2: [23, 24, 25],
+ v3: vec![26, 27, 28],
+ v4: C { f: 29 },
+ v5: Box::new(C { f: 30 }),
+ v6: Some(C { f: 31 })}};
+
+ let p = get_v1(&a);
+ assert_eq!(*p, a.value.v1);
+
+ let p = get_v2(&a, 1);
+ assert_eq!(*p, a.value.v2[1]);
+
+ let p = get_v3(&a, 1);
+ assert_eq!(*p, a.value.v3[1]);
+
+ let p = get_v4(&a, 1);
+ assert_eq!(*p, a.value.v4.f);
+
+ let p = get_v5(&a, 1);
+ assert_eq!(*p, a.value.v5.f);
+
+ let p = get_v6_a(&a, 1);
+ assert_eq!(*p, a.value.v6.unwrap().f);
+
+ let p = get_v6_b(&a, 1);
+ assert_eq!(*p, a.value.v6.unwrap().f);
+
+ let p = get_v6_c(&a, 1);
+ assert_eq!(*p, a.value.v6.unwrap().f);
+
+ let p = get_v5_ref(&a, 1);
+ assert_eq!(*p, a.value.v5.f);
+}
diff --git a/src/test/ui/regions/regions-dependent-autofn.rs b/src/test/ui/regions/regions-dependent-autofn.rs
new file mode 100644
index 000000000..246dbb556
--- /dev/null
+++ b/src/test/ui/regions/regions-dependent-autofn.rs
@@ -0,0 +1,15 @@
+// run-pass
+// Test lifetimes are linked properly when we autoslice a vector.
+// Issue #3148.
+
+// pretty-expanded FIXME #23616
+
+fn subslice<F>(v: F) -> F where F: FnOnce() { v }
+
+fn both<F>(v: F) -> F where F: FnOnce() {
+ subslice(subslice(v))
+}
+
+pub fn main() {
+ both(main);
+}
diff --git a/src/test/ui/regions/regions-dependent-autoslice.rs b/src/test/ui/regions/regions-dependent-autoslice.rs
new file mode 100644
index 000000000..4c5b35ec4
--- /dev/null
+++ b/src/test/ui/regions/regions-dependent-autoslice.rs
@@ -0,0 +1,14 @@
+// run-pass
+// Test lifetimes are linked properly when we autoslice a vector.
+// Issue #3148.
+
+fn subslice1<'r>(v: &'r [usize]) -> &'r [usize] { v }
+
+fn both<'r>(v: &'r [usize]) -> &'r [usize] {
+ subslice1(subslice1(v))
+}
+
+pub fn main() {
+ let v = vec![1,2,3];
+ both(&v);
+}
diff --git a/src/test/ui/regions/regions-dependent-let-ref.rs b/src/test/ui/regions/regions-dependent-let-ref.rs
new file mode 100644
index 000000000..94e3df4b3
--- /dev/null
+++ b/src/test/ui/regions/regions-dependent-let-ref.rs
@@ -0,0 +1,12 @@
+// run-pass
+// Test lifetimes are linked properly when we take reference
+// to interior.
+
+// pretty-expanded FIXME #23616
+
+struct Foo(isize);
+pub fn main() {
+ // Here the lifetime of the `&` should be at least the
+ // block, since a ref binding is created to the interior.
+ let &Foo(ref _x) = &Foo(3);
+}
diff --git a/src/test/ui/regions/regions-early-bound-error-method.rs b/src/test/ui/regions/regions-early-bound-error-method.rs
new file mode 100644
index 000000000..7edcc677d
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error-method.rs
@@ -0,0 +1,26 @@
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+trait GetRef<'a> {
+ fn get(&self) -> &'a isize;
+}
+
+struct Box<'a> {
+ t: &'a isize
+}
+
+impl<'a> GetRef<'a> for Box<'a> {
+ fn get(&self) -> &'a isize {
+ self.t
+ }
+}
+
+impl<'a> Box<'a> {
+ fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
+ g2.get()
+ //~^ ERROR lifetime may not live long enough
+ }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-early-bound-error-method.stderr b/src/test/ui/regions/regions-early-bound-error-method.stderr
new file mode 100644
index 000000000..7f10c051f
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error-method.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-early-bound-error-method.rs:20:9
+ |
+LL | impl<'a> Box<'a> {
+ | -- lifetime `'a` defined here
+LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
+ | -- lifetime `'b` defined here
+LL | g2.get()
+ | ^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-early-bound-error.rs b/src/test/ui/regions/regions-early-bound-error.rs
new file mode 100644
index 000000000..98a69c24f
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error.rs
@@ -0,0 +1,24 @@
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+trait GetRef<'a, T> {
+ fn get(&self) -> &'a T;
+}
+
+struct Box<'a, T:'a> {
+ t: &'a T
+}
+
+impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
+ fn get(&self) -> &'a T {
+ self.t
+ }
+}
+
+fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
+ g1.get()
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-early-bound-error.stderr b/src/test/ui/regions/regions-early-bound-error.stderr
new file mode 100644
index 000000000..eb4cd5ca7
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-early-bound-error.rs:19:5
+ |
+LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | g1.get()
+ | ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs b/src/test/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs
new file mode 100644
index 000000000..fe50a7dd1
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs
@@ -0,0 +1,35 @@
+// run-pass
+#![allow(unused_imports)]
+// Test that we are able to compile calls to associated fns like
+// `decode()` where the bound on the `Self` parameter references a
+// lifetime parameter of the trait. This example indicates why trait
+// lifetime parameters must be early bound in the type of the
+// associated item.
+
+// pretty-expanded FIXME #23616
+
+use std::marker;
+
+pub enum Value<'v> {
+ A(&'v str),
+ B,
+}
+
+pub trait Decoder<'v> {
+ fn read(&mut self) -> Value<'v>;
+}
+
+pub trait Decodable<'v, D: Decoder<'v>> {
+ fn decode(d: &mut D) -> Self;
+}
+
+impl<'v, D: Decoder<'v>> Decodable<'v, D> for () {
+ fn decode(d: &mut D) -> () {
+ match d.read() {
+ Value::A(..) => (),
+ Value::B => Decodable::decode(d),
+ }
+ }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/regions/regions-early-bound-trait-param.rs b/src/test/ui/regions/regions-early-bound-trait-param.rs
new file mode 100644
index 000000000..a28bd14ba
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-trait-param.rs
@@ -0,0 +1,132 @@
+// run-pass
+// Tests that you can use an early-bound lifetime parameter as
+// on of the generic parameters in a trait.
+
+trait Trait<'a> {
+ fn long(&'a self) -> isize;
+ fn short<'b>(&'b self) -> isize;
+}
+
+fn poly_invoke<'c, T: Trait<'c>>(x: &'c T) -> (isize, isize) {
+ let l = x.long();
+ let s = x.short();
+ (l,s)
+}
+
+fn object_invoke1<'d>(x: &'d dyn Trait<'d>) -> (isize, isize) {
+ let l = x.long();
+ let s = x.short();
+ (l,s)
+}
+
+struct Struct1<'e> {
+ f: &'e (dyn Trait<'e>+'e)
+}
+
+fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (isize,isize) {
+ let l = x.f.long();
+ let s = x.f.short();
+ (l,s)
+}
+
+struct Struct2<'h, 'i:'h> {
+ f: &'h (dyn Trait<'i>+'h)
+}
+
+fn object_invoke2<'j, 'k>(x: &'k dyn Trait<'j>) -> isize {
+ x.short()
+}
+
+fn field_invoke2<'l, 'm, 'n>(x: &'n Struct2<'l,'m>) -> isize {
+ x.f.short()
+}
+
+trait MakerTrait {
+ fn mk() -> Self;
+}
+
+fn make_val<T:MakerTrait>() -> T {
+ MakerTrait::mk()
+}
+
+trait RefMakerTrait<'q> {
+ fn mk(_: Self) -> &'q Self;
+}
+
+fn make_ref<'r, T:RefMakerTrait<'r>>(t:T) -> &'r T {
+ RefMakerTrait::mk(t)
+}
+
+impl<'s> Trait<'s> for (isize,isize) {
+ fn long(&'s self) -> isize {
+ let &(x,_) = self;
+ x
+ }
+ fn short<'b>(&'b self) -> isize {
+ let &(_,y) = self;
+ y
+ }
+}
+
+impl<'t> MakerTrait for Box<dyn Trait<'t>+'static> {
+ fn mk() -> Box<dyn Trait<'t>+'static> {
+ let tup: Box<(isize, isize)> = Box::new((4,5));
+ tup as Box<dyn Trait>
+ }
+}
+
+enum List<'l> {
+ Cons(isize, &'l List<'l>),
+ Null
+}
+
+impl<'l> List<'l> {
+ fn car<'m>(&'m self) -> isize {
+ match self {
+ &List::Cons(car, _) => car,
+ &List::Null => panic!(),
+ }
+ }
+ fn cdr<'n>(&'n self) -> &'l List<'l> {
+ match self {
+ &List::Cons(_, cdr) => cdr,
+ &List::Null => panic!(),
+ }
+ }
+}
+
+impl<'t> RefMakerTrait<'t> for List<'t> {
+ fn mk(l:List<'t>) -> &'t List<'t> {
+ l.cdr()
+ }
+}
+
+pub fn main() {
+ let t = (2,3);
+ let o = &t as &dyn Trait;
+ let s1 = Struct1 { f: o };
+ let s2 = Struct2 { f: o };
+ assert_eq!(poly_invoke(&t), (2,3));
+ assert_eq!(object_invoke1(&t), (2,3));
+ assert_eq!(field_invoke1(&s1), (2,3));
+ assert_eq!(object_invoke2(&t), 3);
+ assert_eq!(field_invoke2(&s2), 3);
+
+ let m : Box<dyn Trait> = make_val();
+ // assert_eq!(object_invoke1(&*m), (4,5));
+ // ~~~~~~~~~~~~~~~~~~~
+ // this call yields a compilation error; see ui/span/dropck-object-cycle.rs
+ // for details.
+ assert_eq!(object_invoke2(&*m), 5);
+
+ // The RefMakerTrait above is pretty strange (i.e., it is strange
+ // to consume a value of type T and return a &T). Easiest thing
+ // that came to my mind: consume a cell of a linked list and
+ // return a reference to the list it points to.
+ let l0 = List::Null;
+ let l1 = List::Cons(1, &l0);
+ let l2 = List::Cons(2, &l1);
+ let rl1 = &l1;
+ let r = make_ref(l2);
+ assert_eq!(rl1.car(), r.car());
+}
diff --git a/src/test/ui/regions/regions-early-bound-used-in-bound-method.rs b/src/test/ui/regions/regions-early-bound-used-in-bound-method.rs
new file mode 100644
index 000000000..a778dae1e
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-used-in-bound-method.rs
@@ -0,0 +1,30 @@
+// run-pass
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+
+trait GetRef<'a> {
+ fn get(&self) -> &'a isize;
+}
+
+#[derive(Copy, Clone)]
+struct Box<'a> {
+ t: &'a isize
+}
+
+impl<'a> GetRef<'a> for Box<'a> {
+ fn get(&self) -> &'a isize {
+ self.t
+ }
+}
+
+impl<'a> Box<'a> {
+ fn add<'b,G:GetRef<'b>>(&self, g2: G) -> isize {
+ *self.t + *g2.get()
+ }
+}
+
+pub fn main() {
+ let b1 = Box { t: &3 };
+ assert_eq!(b1.add(b1), 6);
+}
diff --git a/src/test/ui/regions/regions-early-bound-used-in-bound.rs b/src/test/ui/regions/regions-early-bound-used-in-bound.rs
new file mode 100644
index 000000000..6ccc99e84
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-used-in-bound.rs
@@ -0,0 +1,28 @@
+// run-pass
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+
+trait GetRef<'a, T> {
+ fn get(&self) -> &'a T;
+}
+
+#[derive(Copy, Clone)]
+struct Box<'a, T:'a> {
+ t: &'a T
+}
+
+impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
+ fn get(&self) -> &'a T {
+ self.t
+ }
+}
+
+fn add<'a,G:GetRef<'a, isize>>(g1: G, g2: G) -> isize {
+ *g1.get() + *g2.get()
+}
+
+pub fn main() {
+ let b1 = Box { t: &3 };
+ assert_eq!(add(b1, b1), 6);
+}
diff --git a/src/test/ui/regions/regions-early-bound-used-in-type-param.rs b/src/test/ui/regions/regions-early-bound-used-in-type-param.rs
new file mode 100644
index 000000000..d58c17ad9
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-used-in-type-param.rs
@@ -0,0 +1,28 @@
+// run-pass
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+
+trait Get<T> {
+ fn get(&self) -> T;
+}
+
+#[derive(Copy, Clone)]
+struct Box<T> {
+ t: T
+}
+
+impl<T:Clone> Get<T> for Box<T> {
+ fn get(&self) -> T {
+ self.t.clone()
+ }
+}
+
+fn add<'a,G:Get<&'a isize>>(g1: G, g2: G) -> isize {
+ *g1.get() + *g2.get()
+}
+
+pub fn main() {
+ let b1 = Box { t: &3 };
+ assert_eq!(add(b1, b1), 6);
+}
diff --git a/src/test/ui/regions/regions-escape-into-other-fn.rs b/src/test/ui/regions/regions-escape-into-other-fn.rs
new file mode 100644
index 000000000..65f4c1b6a
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-into-other-fn.rs
@@ -0,0 +1,8 @@
+// run-pass
+fn foo(x: &usize) -> &usize { x }
+fn bar(x: &usize) -> usize { *x }
+
+pub fn main() {
+ let p: Box<_> = Box::new(3);
+ assert_eq!(bar(foo(&*p)), 3);
+}
diff --git a/src/test/ui/regions/regions-escape-method.rs b/src/test/ui/regions/regions-escape-method.rs
new file mode 100644
index 000000000..69c01ae69
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-method.rs
@@ -0,0 +1,16 @@
+// Test a method call where the parameter `B` would (illegally) be
+// inferred to a region bound in the method argument. If this program
+// were accepted, then the closure passed to `s.f` could escape its
+// argument.
+
+struct S;
+
+impl S {
+ fn f<B, F>(&self, _: F) where F: FnOnce(&i32) -> B {
+ }
+}
+
+fn main() {
+ let s = S;
+ s.f(|p| p) //~ ERROR lifetime may not live long enough
+}
diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr
new file mode 100644
index 000000000..9f425125b
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-method.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-escape-method.rs:15:13
+ |
+LL | s.f(|p| p)
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 i32
+ | has type `&'1 i32`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.rs b/src/test/ui/regions/regions-escape-via-trait-or-not.rs
new file mode 100644
index 000000000..ac0e56de4
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.rs
@@ -0,0 +1,22 @@
+#![allow(dead_code)]
+
+trait Deref {
+ fn get(self) -> isize;
+}
+
+impl<'a> Deref for &'a isize {
+ fn get(self) -> isize {
+ *self
+ }
+}
+
+fn with<R:Deref, F>(f: F) -> isize where F: FnOnce(&isize) -> R {
+ f(&3).get()
+}
+
+fn return_it() -> isize {
+ with(|o| o) //~ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
new file mode 100644
index 000000000..cae6c33ac
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-escape-via-trait-or-not.rs:18:14
+ |
+LL | with(|o| o)
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 isize
+ | has type `&'1 isize`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-expl-self.rs b/src/test/ui/regions/regions-expl-self.rs
new file mode 100644
index 000000000..f7315d628
--- /dev/null
+++ b/src/test/ui/regions/regions-expl-self.rs
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+// Test that you can insert an explicit lifetime in explicit self.
+
+// pretty-expanded FIXME #23616
+
+struct Foo {
+ f: usize
+}
+
+impl Foo {
+ pub fn foo<'a>(&'a self) {}
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-fn-subtyping-2.rs b/src/test/ui/regions/regions-fn-subtyping-2.rs
new file mode 100644
index 000000000..83949ddba
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping-2.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![allow(dead_code)]
+// Issue #2263.
+
+// Here, `f` is a function that takes a pointer `x` and a function
+// `g`, where `g` requires its argument `y` to be in the same region
+// that `x` is in.
+// pretty-expanded FIXME #23616
+
+fn has_same_region(f: Box<dyn for<'a> FnMut(&'a isize, Box<dyn FnMut(&'a isize)>)>) {
+ // `f` should be the type that `wants_same_region` wants, but
+ // right now the compiler complains that it isn't.
+ wants_same_region(f);
+}
+
+fn wants_same_region(_f: Box<dyn for<'b> FnMut(&'b isize, Box<dyn FnMut(&'b isize)>)>) {
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.rs
new file mode 100644
index 000000000..539221b5a
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.rs
@@ -0,0 +1,51 @@
+// In this fn, the type `F` is a function that takes a reference to a
+// struct and returns another reference with the same lifetime.
+//
+// Meanwhile, the bare fn `foo` takes a reference to a struct with
+// *ANY* lifetime and returns a reference with the 'static lifetime.
+// This can safely be considered to be an instance of `F` because all
+// lifetimes are sublifetimes of 'static.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct S;
+
+// Given 'cx, return 'cx
+type F = for<'cx> fn(&'cx S) -> &'cx S;
+fn want_F(f: F) {}
+
+// Given anything, return 'static
+type G = for<'cx> fn(&'cx S) -> &'static S;
+fn want_G(f: G) {}
+
+// Should meet both.
+fn foo(x: &S) -> &'static S {
+ panic!()
+}
+
+// Should meet both.
+fn bar<'a, 'b>(x: &'a S) -> &'b S {
+ panic!()
+}
+
+// Meets F, but not G.
+fn baz(x: &S) -> &S {
+ panic!()
+}
+
+fn supply_F() {
+ want_F(foo);
+
+ want_F(bar);
+
+ want_F(baz);
+}
+
+fn supply_G() {
+ want_G(foo);
+ want_G(bar);
+ want_G(baz); //~ ERROR mismatched types
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr
new file mode 100644
index 000000000..d87d0d2f6
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12
+ |
+LL | want_G(baz);
+ | ------ ^^^ one type is more general than the other
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
+ found fn item `for<'r> fn(&'r S) -> &'r S {baz}`
+note: function defined here
+ --> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4
+ |
+LL | fn want_G(f: G) {}
+ | ^^^^^^ ----
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs
new file mode 100644
index 000000000..de14d5ba8
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs
@@ -0,0 +1,48 @@
+// In this fn, the type `F` is a function that takes a reference to a
+// struct and returns another reference with the same lifetime.
+//
+// Meanwhile, the bare fn `foo` takes a reference to a struct with
+// *ANY* lifetime and returns a reference with the 'static lifetime.
+// This can safely be considered to be an instance of `F` because all
+// lifetimes are sublifetimes of 'static.
+//
+// check-pass
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+
+struct S;
+
+// Given 'cx, return 'cx
+type F = for<'cx> fn(&'cx S) -> &'cx S;
+fn want_F(f: F) {}
+
+// Given anything, return 'static
+type G = for<'cx> fn(&'cx S) -> &'static S;
+fn want_G(f: G) {}
+
+// Should meet both.
+fn foo(x: &S) -> &'static S {
+ panic!()
+}
+
+// Should meet both.
+fn bar<'a, 'b>(x: &'a S) -> &'b S {
+ panic!()
+}
+
+// Meets F, but not G.
+fn baz(x: &S) -> &S {
+ panic!()
+}
+
+fn supply_F() {
+ want_F(foo);
+
+ want_F(bar);
+
+ want_F(baz);
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-fn-subtyping.rs b/src/test/ui/regions/regions-fn-subtyping.rs
new file mode 100644
index 000000000..9570359c6
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping.rs
@@ -0,0 +1,30 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+// Issue #2263.
+
+// pretty-expanded FIXME #23616
+
+#![allow(unused_variables)]
+
+// Should pass region checking.
+fn ok(f: Box<dyn FnMut(&usize)>) {
+ // Here, g is a function that can accept a usize pointer with
+ // lifetime r, and f is a function that can accept a usize pointer
+ // with any lifetime. The assignment g = f should be OK (i.e.,
+ // f's type should be a subtype of g's type), because f can be
+ // used in any context that expects g's type. But this currently
+ // fails.
+ let mut g: Box<dyn for<'r> FnMut(&'r usize)> = Box::new(|x| { });
+ g = f;
+}
+
+// This version is the same as above, except that here, g's type is
+// inferred.
+fn ok_inferred(f: Box<dyn FnMut(&usize)>) {
+ let mut g: Box<dyn for<'r> FnMut(&'r usize)> = Box::new(|_| {});
+ g = f;
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.rs b/src/test/ui/regions/regions-free-region-ordering-callee-4.rs
new file mode 100644
index 000000000..de58dd0b1
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.rs
@@ -0,0 +1,11 @@
+// Tests that callees correctly infer an ordering between free regions
+// that appear in their parameter list. See also
+// regions-free-region-ordering-caller.rs
+
+fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+ //~^ ERROR reference has a longer lifetime than the data it references
+ // Do not infer ordering from closure argument types.
+ let z: Option<&'a &'b usize> = None;
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr
new file mode 100644
index 000000000..1df7ca0e3
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-free-region-ordering-callee-4.rs:5:68
+ |
+LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime `'a` as defined here
+ --> $DIR/regions-free-region-ordering-callee-4.rs:5:14
+ |
+LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+ | ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined here
+ --> $DIR/regions-free-region-ordering-callee-4.rs:5:18
+ |
+LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+ | ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.rs b/src/test/ui/regions/regions-free-region-ordering-callee.rs
new file mode 100644
index 000000000..8158e81e1
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee.rs
@@ -0,0 +1,30 @@
+// Tests that callees correctly infer an ordering between free regions
+// that appear in their parameter list. See also
+// regions-free-region-ordering-caller.rs
+
+fn ordering1<'a, 'b>(x: &'a &'b usize) -> &'a usize {
+ // It is safe to assume that 'a <= 'b due to the type of x
+ let y: &'b usize = &**x;
+ return y;
+}
+
+fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
+ // However, it is not safe to assume that 'b <= 'a
+ &*y
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
+ // Do not infer an ordering from the return value.
+ let z: &'b usize = &*x;
+ //~^ ERROR lifetime may not live long enough
+ panic!();
+}
+
+// see regions-free-region-ordering-callee-4.rs
+
+fn ordering5<'a, 'b>(a: &'a usize, b: &'b usize, x: Option<&'a &'b usize>) {
+ let z: Option<&'a &'b usize> = None;
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.stderr b/src/test/ui/regions/regions-free-region-ordering-callee.stderr
new file mode 100644
index 000000000..a1b46a692
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-callee.rs:13:5
+ |
+LL | fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // However, it is not safe to assume that 'b <= 'a
+LL | &*y
+ | ^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-callee.rs:19:12
+ |
+LL | fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // Do not infer an ordering from the return value.
+LL | let z: &'b usize = &*x;
+ | ^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs
new file mode 100644
index 000000000..2e83c3258
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs
@@ -0,0 +1,23 @@
+// Test various ways to construct a pointer with a longer lifetime
+// than the thing it points at and ensure that they result in
+// errors. See also regions-free-region-ordering-callee.rs
+
+struct Paramd<'a> { x: &'a usize }
+
+fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+ let z: Option<&'b &'a usize> = None;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+ let y: Paramd<'a> = Paramd { x: a };
+ let z: Option<&'b Paramd<'a>> = None;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+ let z: Option<&'a &'b usize> = None;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.stderr
new file mode 100644
index 000000000..c79ed50c6
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.stderr
@@ -0,0 +1,39 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-caller.rs:8:12
+ |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let z: Option<&'b &'a usize> = None;
+ | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-caller.rs:14:12
+ |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let y: Paramd<'a> = Paramd { x: a };
+LL | let z: Option<&'b Paramd<'a>> = None;
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-caller.rs:19:12
+ |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let z: Option<&'a &'b usize> = None;
+ | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.rs b/src/test/ui/regions/regions-free-region-ordering-caller1.rs
new file mode 100644
index 000000000..f32455616
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller1.rs
@@ -0,0 +1,14 @@
+// Test various ways to construct a pointer with a longer lifetime
+// than the thing it points at and ensure that they result in
+// errors. See also regions-free-region-ordering-callee.rs
+
+fn call1<'a>(x: &'a usize) {
+ // Test that creating a pointer like
+ // &'a &'z usize requires that 'a <= 'z:
+ let y: usize = 3;
+ let z: &'a & usize = &(&y);
+ //~^ ERROR temporary value dropped while borrowed
+ //~^^ ERROR `y` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
new file mode 100644
index 000000000..8042b1740
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
@@ -0,0 +1,32 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+ |
+LL | fn call1<'a>(x: &'a usize) {
+ | -- lifetime `'a` defined here
+...
+LL | let z: &'a & usize = &(&y);
+ | ----------- ^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'a`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0597]: `y` does not live long enough
+ --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+ |
+LL | fn call1<'a>(x: &'a usize) {
+ | -- lifetime `'a` defined here
+...
+LL | let z: &'a & usize = &(&y);
+ | ----------- ^^^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `y` is borrowed for `'a`
+...
+LL | }
+ | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.rs b/src/test/ui/regions/regions-free-region-ordering-incorrect.rs
new file mode 100644
index 000000000..1aee6e876
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.rs
@@ -0,0 +1,22 @@
+// Test that free regions ordering only goes one way. That is,
+// we have `&'a Node<'b, T>`, which implies that `'a <= 'b`,
+// but not `'b <= 'a`. Hence, returning `&self.val` (which has lifetime
+// `'a`) where `'b` is expected yields an error.
+//
+// This test began its life as a test for issue #4325.
+
+struct Node<'b, T: 'b> {
+ val: T,
+ next: Option<&'b Node<'b, T>>
+}
+
+impl<'b, T> Node<'b, T> {
+ fn get<'a>(&'a self) -> &'b T {
+ match self.next { //~ ERROR lifetime may not live long enough
+ Some(ref next) => next.get(),
+ None => &self.val
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr
new file mode 100644
index 000000000..f7c75033c
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr
@@ -0,0 +1,17 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-incorrect.rs:15:9
+ |
+LL | impl<'b, T> Node<'b, T> {
+ | -- lifetime `'b` defined here
+LL | fn get<'a>(&'a self) -> &'b T {
+ | -- lifetime `'a` defined here
+LL | / match self.next {
+LL | | Some(ref next) => next.get(),
+LL | | None => &self.val
+LL | | }
+ | |_________^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs b/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
new file mode 100644
index 000000000..7c2e1aeee
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(dead_code)]
+// Test that we recognize that if you have
+//
+// 'a : 'static
+//
+// then
+//
+// 'a : 'b
+
+fn test<'a,'b>(x: &'a i32) -> &'b i32
+ where 'a: 'static //~ WARN unnecessary lifetime parameter `'a`
+{
+ x
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr b/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
new file mode 100644
index 000000000..70ed418d5
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
@@ -0,0 +1,10 @@
+warning: unnecessary lifetime parameter `'a`
+ --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:12:11
+ |
+LL | where 'a: 'static
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'a`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/regions/regions-glb-free-free.rs b/src/test/ui/regions/regions-glb-free-free.rs
new file mode 100644
index 000000000..0370a5192
--- /dev/null
+++ b/src/test/ui/regions/regions-glb-free-free.rs
@@ -0,0 +1,29 @@
+mod argparse {
+ pub struct Flag<'a> {
+ name: &'a str,
+ pub desc: &'a str,
+ max_count: usize,
+ value: usize
+ }
+
+ pub fn flag<'r>(name: &'r str, desc: &'r str) -> Flag<'r> {
+ Flag { name: name, desc: desc, max_count: 1, value: 0 }
+ }
+
+ impl<'a> Flag<'a> {
+ pub fn set_desc(self, s: &str) -> Flag<'a> {
+ Flag { //~ ERROR explicit lifetime required in the type of `s` [E0621]
+ name: self.name,
+ desc: s,
+ max_count: self.max_count,
+ value: self.value
+ }
+ }
+ }
+}
+
+fn main () {
+ let f : argparse::Flag = argparse::flag("flag", "My flag");
+ let updated_flag = f.set_desc("My new flag");
+ assert_eq!(updated_flag.desc, "My new flag");
+}
diff --git a/src/test/ui/regions/regions-glb-free-free.stderr b/src/test/ui/regions/regions-glb-free-free.stderr
new file mode 100644
index 000000000..575037a0a
--- /dev/null
+++ b/src/test/ui/regions/regions-glb-free-free.stderr
@@ -0,0 +1,16 @@
+error[E0621]: explicit lifetime required in the type of `s`
+ --> $DIR/regions-glb-free-free.rs:15:13
+ |
+LL | pub fn set_desc(self, s: &str) -> Flag<'a> {
+ | ---- help: add explicit lifetime `'a` to the type of `s`: `&'a str`
+LL | / Flag {
+LL | | name: self.name,
+LL | | desc: s,
+LL | | max_count: self.max_count,
+LL | | value: self.value
+LL | | }
+ | |_____________^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs
new file mode 100644
index 000000000..38fc9c462
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs
@@ -0,0 +1,30 @@
+// Illustrates the "projection gap": in this test, even though we know
+// that `T::Foo: 'x`, that does not tell us that `T: 'x`, because
+// there might be other ways for the caller of `func` to show that
+// `T::Foo: 'x` holds (e.g., where-clause).
+
+trait Trait1<'x> {
+ type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+{
+ wf::<&'x T>();
+ //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn caller2<'x, T:Trait1<'x>>(t: &'x T)
+{
+ wf::<&'x T::Foo>(); // OK
+}
+
+fn caller3<'x, T:Trait1<'x>>(t: &'x T::Foo)
+{
+ wf::<&'x T::Foo>(); // OK
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
new file mode 100644
index 000000000..7c9f40556
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
@@ -0,0 +1,14 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:5
+ |
+LL | wf::<&'x T>();
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn func<'x, T:Trait1<'x> + 'x>(t: &'x T::Foo)
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
new file mode 100644
index 000000000..a481a9cc5
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
@@ -0,0 +1,23 @@
+// Along with the other tests in this series, illustrates the
+// "projection gap": in this test, we know that `T: 'x`, and that is
+// enough to conclude that `T::Foo: 'x`.
+
+// check-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Trait1<'x> {
+ type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T)
+{
+ wf::<&'x T::Foo>();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
new file mode 100644
index 000000000..a627cbbd8
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
@@ -0,0 +1,23 @@
+// Along with the other tests in this series, illustrates the
+// "projection gap": in this test, we know that `T::Foo: 'x`, and that
+// is (naturally) enough to conclude that `T::Foo: 'x`.
+
+// check-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Trait1<'x> {
+ type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+{
+ wf::<&'x T::Foo>();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
new file mode 100644
index 000000000..5158c2893
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
@@ -0,0 +1,23 @@
+// Along with the other tests in this series, illustrates the
+// "projection gap": in this test, we know that `T: 'x`, and that
+// is (naturally) enough to conclude that `T: 'x`.
+
+// check-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Trait1<'x> {
+ type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T)
+{
+ wf::<&'x T>();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
new file mode 100644
index 000000000..c1dab6086
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
@@ -0,0 +1,26 @@
+// The "projection gap" is particularly "fun" around higher-ranked
+// projections. This is because the current code is hard-coded to say
+// that a projection that contains escaping regions, like `<T as
+// Trait2<'y, 'z>>::Foo` where `'z` is bound, can only be found to
+// outlive a region if all components that appear free (`'y`, where)
+// outlive that region. However, we DON'T add those components to the
+// implied bounds set, but rather we treat projections with escaping
+// regions as opaque entities, just like projections without escaping
+// regions.
+
+trait Trait1<T> { }
+
+trait Trait2<'a, 'b> {
+ type Foo;
+}
+
+// As a side-effect of the conservative process above, the type of
+// this argument `t` is not automatically considered well-formed,
+// since for it to be WF, we would need to know that `'y: 'x`, but we
+// do not infer that.
+fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+ //~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+{
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
new file mode 100644
index 000000000..6844e8665
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+ --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49
+ |
+LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+ | ++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/regions/regions-in-enums-anon.rs b/src/test/ui/regions/regions-in-enums-anon.rs
new file mode 100644
index 000000000..da65cb791
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums-anon.rs
@@ -0,0 +1,7 @@
+// Test that anonymous lifetimes are not permitted in enum declarations
+
+enum Foo {
+ Bar(&isize) //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-enums-anon.stderr b/src/test/ui/regions/regions-in-enums-anon.stderr
new file mode 100644
index 000000000..ed547aa9c
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums-anon.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/regions-in-enums-anon.rs:4:9
+ |
+LL | Bar(&isize)
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ enum Foo<'a> {
+LL ~ Bar(&'a isize)
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/regions/regions-in-enums.rs b/src/test/ui/regions/regions-in-enums.rs
new file mode 100644
index 000000000..8cf553a0f
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums.rs
@@ -0,0 +1,20 @@
+// Test that lifetimes must be declared for use on enums.
+// See also regions-undeclared.rs
+
+enum Yes0<'lt> {
+ X3(&'lt usize)
+}
+
+enum Yes1<'a> {
+ X4(&'a usize)
+}
+
+enum No0 {
+ X5(&'foo usize) //~ ERROR use of undeclared lifetime name `'foo`
+}
+
+enum No1 {
+ X6(&'a usize) //~ ERROR use of undeclared lifetime name `'a`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-enums.stderr b/src/test/ui/regions/regions-in-enums.stderr
new file mode 100644
index 000000000..665376532
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums.stderr
@@ -0,0 +1,19 @@
+error[E0261]: use of undeclared lifetime name `'foo`
+ --> $DIR/regions-in-enums.rs:13:9
+ |
+LL | enum No0 {
+ | - help: consider introducing lifetime `'foo` here: `<'foo>`
+LL | X5(&'foo usize)
+ | ^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-in-enums.rs:17:9
+ |
+LL | enum No1 {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | X6(&'a usize)
+ | ^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-in-structs-anon.rs b/src/test/ui/regions/regions-in-structs-anon.rs
new file mode 100644
index 000000000..7cb2ce0db
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs-anon.rs
@@ -0,0 +1,7 @@
+// Test that anonymous lifetimes are not permitted in struct declarations
+
+struct Foo {
+ x: &isize //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-structs-anon.stderr b/src/test/ui/regions/regions-in-structs-anon.stderr
new file mode 100644
index 000000000..992d25c9f
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs-anon.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/regions-in-structs-anon.rs:4:8
+ |
+LL | x: &isize
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ struct Foo<'a> {
+LL ~ x: &'a isize
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/regions/regions-in-structs.rs b/src/test/ui/regions/regions-in-structs.rs
new file mode 100644
index 000000000..71f718ba2
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs.rs
@@ -0,0 +1,15 @@
+struct Yes1<'a> {
+ x: &'a usize,
+}
+
+struct Yes2<'a> {
+ x: &'a usize,
+}
+
+struct StructDecl {
+ a: &'a isize, //~ ERROR use of undeclared lifetime name `'a`
+ b: &'a isize, //~ ERROR use of undeclared lifetime name `'a`
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-structs.stderr b/src/test/ui/regions/regions-in-structs.stderr
new file mode 100644
index 000000000..5dfdc2ee9
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs.stderr
@@ -0,0 +1,20 @@
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-in-structs.rs:10:9
+ |
+LL | struct StructDecl {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | a: &'a isize,
+ | ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-in-structs.rs:11:9
+ |
+LL | struct StructDecl {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | a: &'a isize,
+LL | b: &'a isize,
+ | ^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-infer-at-fn-not-param.rs b/src/test/ui/regions/regions-infer-at-fn-not-param.rs
new file mode 100644
index 000000000..fb9c5d5c2
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-at-fn-not-param.rs
@@ -0,0 +1,19 @@
+struct Parameterized1<'a> {
+ g: Box<dyn FnMut() + 'a>
+}
+
+struct NotParameterized1 {
+ g: Box<dyn FnMut() + 'static>
+}
+
+struct NotParameterized2 {
+ g: Box<dyn FnMut() + 'static>
+}
+
+fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p }
+//~^ ERROR explicit lifetime required in the type of `p`
+
+fn take3(p: NotParameterized1) -> NotParameterized1 { p }
+fn take4(p: NotParameterized2) -> NotParameterized2 { p }
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-at-fn-not-param.stderr b/src/test/ui/regions/regions-infer-at-fn-not-param.stderr
new file mode 100644
index 000000000..8cfc44f6a
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-at-fn-not-param.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `p`
+ --> $DIR/regions-infer-at-fn-not-param.rs:13:57
+ |
+LL | fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p }
+ | -------------- ^ lifetime `'a` required
+ | |
+ | help: add explicit lifetime `'a` to the type of `p`: `Parameterized1<'a>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-addr-of.rs b/src/test/ui/regions/regions-infer-borrow-scope-addr-of.rs
new file mode 100644
index 000000000..5d8ad932e
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-addr-of.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+use std::mem::swap;
+
+pub fn main() {
+ let mut x = 4;
+
+ for i in 0_usize..3 {
+ // ensure that the borrow in this alt
+ // does not interfere with the swap
+ // below. note that it would it you
+ // naively borrowed &x for the lifetime
+ // of the variable x, as we once did
+ match i {
+ i => {
+ let y = &x;
+ assert!(i < *y);
+ }
+ }
+ let mut y = 4;
+ swap(&mut y, &mut x);
+ }
+}
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-too-big.rs b/src/test/ui/regions/regions-infer-borrow-scope-too-big.rs
new file mode 100644
index 000000000..250b41da5
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-too-big.rs
@@ -0,0 +1,16 @@
+struct Point {
+ x: isize,
+ y: isize,
+}
+
+fn x_coord<'r>(p: &'r Point) -> &'r isize {
+ return &p.x;
+}
+
+fn foo<'a>(p: Box<Point>) -> &'a isize {
+ let xc = x_coord(&*p);
+ assert_eq!(*xc, 3);
+ return xc; //~ ERROR cannot return value referencing local data `*p`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr b/src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr
new file mode 100644
index 000000000..2c7a6e8b5
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*p`
+ --> $DIR/regions-infer-borrow-scope-too-big.rs:13:12
+ |
+LL | let xc = x_coord(&*p);
+ | --- `*p` is borrowed here
+LL | assert_eq!(*xc, 3);
+LL | return xc;
+ | ^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-view.rs b/src/test/ui/regions/regions-infer-borrow-scope-view.rs
new file mode 100644
index 000000000..349b52044
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-view.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+
+fn view<T>(x: &[T]) -> &[T] {x}
+
+pub fn main() {
+ let v = vec![1, 2, 3];
+ let x = view(&v);
+ let y = view(x);
+ assert!((v[0] == x[0]) && (v[0] == y[0]));
+}
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs b/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs
new file mode 100644
index 000000000..dca26742d
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+fn borrow<T>(x: &T) -> &T {x}
+
+pub fn main() {
+ let x: Box<_> = Box::new(3);
+ loop {
+ let y = borrow(&*x);
+ assert_eq!(*x, *y);
+ break;
+ }
+}
diff --git a/src/test/ui/regions/regions-infer-borrow-scope.rs b/src/test/ui/regions/regions-infer-borrow-scope.rs
new file mode 100644
index 000000000..b4a050bf1
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![allow(dead_code)]
+
+struct Point {x: isize, y: isize}
+
+fn x_coord(p: &Point) -> &isize {
+ return &p.x;
+}
+
+pub fn main() {
+ let p: Box<_> = Box::new(Point {x: 3, y: 4});
+ let xc = x_coord(&*p);
+ assert_eq!(*xc, 3);
+}
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.rs b/src/test/ui/regions/regions-infer-bound-from-trait-self.rs
new file mode 100644
index 000000000..d15bfffe9
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.rs
@@ -0,0 +1,51 @@
+// Test that we can derive lifetime bounds on `Self` from trait
+// inheritance.
+
+trait Static : 'static { }
+
+trait Is<'a> : 'a { }
+
+struct Inv<'a> {
+ x: Option<&'a mut &'a isize>
+}
+
+fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
+
+// In these case, `Self` inherits `'static`.
+
+trait InheritsFromStatic : Sized + 'static {
+ fn foo1<'a>(self, x: Inv<'a>) {
+ check_bound(x, self)
+ }
+}
+trait InheritsFromStaticIndirectly : Sized + Static {
+ fn foo1<'a>(self, x: Inv<'a>) {
+ check_bound(x, self)
+ }
+}
+
+
+// In these case, `Self` inherits `'a`.
+
+trait InheritsFromIs<'a> : Sized + 'a {
+ fn foo(self, x: Inv<'a>) {
+ check_bound(x, self)
+ }
+}
+
+trait InheritsFromIsIndirectly<'a> : Sized + Is<'a> {
+ fn foo(self, x: Inv<'a>) {
+ check_bound(x, self)
+ }
+}
+
+// In this case, `Self` inherits nothing.
+
+trait InheritsFromNothing<'a> : Sized {
+ fn foo(self, x: Inv<'a>) {
+ check_bound(x, self)
+ //~^ ERROR parameter type `Self` may not live long enough
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
new file mode 100644
index 000000000..e88f79a3a
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
@@ -0,0 +1,12 @@
+error[E0309]: the parameter type `Self` may not live long enough
+ --> $DIR/regions-infer-bound-from-trait-self.rs:46:9
+ |
+LL | check_bound(x, self)
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `Self: 'a`...
+ = note: ...so that the type `Self` will meet its required lifetime bounds
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.rs b/src/test/ui/regions/regions-infer-bound-from-trait.rs
new file mode 100644
index 000000000..610452182
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait.rs
@@ -0,0 +1,40 @@
+// Test that we can derive lifetime bounds on type parameters
+// from trait inheritance.
+
+trait Static : 'static { }
+
+trait Is<'a> : 'a { }
+
+struct Inv<'a> {
+ x: Option<&'a mut &'a isize>
+}
+
+fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
+
+// In all of these cases, we can derive a bound for A that is longer
+// than 'a based on the trait bound of A:
+
+fn foo1<'a,A:Static>(x: Inv<'a>, a: A) {
+ check_bound(x, a)
+}
+
+fn foo2<'a,A:Static>(x: Inv<'static>, a: A) {
+ check_bound(x, a)
+}
+
+fn foo3<'a,A:Is<'a>>(x: Inv<'a>, a: A) {
+ check_bound(x, a)
+}
+
+// In these cases, there is no trait bound, so we cannot derive any
+// bound for A and we get an error:
+
+fn bar1<'a,A>(x: Inv<'a>, a: A) {
+ check_bound(x, a) //~ ERROR parameter type `A` may not live long enough
+}
+
+fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
+ check_bound(x, a) //~ ERROR parameter type `A` may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
new file mode 100644
index 000000000..3ee71543d
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
@@ -0,0 +1,25 @@
+error[E0309]: the parameter type `A` may not live long enough
+ --> $DIR/regions-infer-bound-from-trait.rs:33:5
+ |
+LL | check_bound(x, a)
+ | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bar1<'a,A: 'a>(x: Inv<'a>, a: A) {
+ | ++++
+
+error[E0309]: the parameter type `A` may not live long enough
+ --> $DIR/regions-infer-bound-from-trait.rs:37:5
+ |
+LL | check_bound(x, a)
+ | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bar2<'a,'b,A:Is<'b> + 'a>(x: Inv<'a>, y: Inv<'b>, a: A) {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-infer-call-2.rs b/src/test/ui/regions/regions-infer-call-2.rs
new file mode 100644
index 000000000..a288d2e4d
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-call-2.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+fn takes_two(x: &isize, y: &isize) -> isize { *x + *y }
+
+fn with<T, F>(f: F) -> T where F: FnOnce(&isize) -> T {
+ f(&20)
+}
+
+fn has_one<'a>(x: &'a isize) -> isize {
+ with(|y| takes_two(x, y))
+}
+
+pub fn main() {
+ assert_eq!(has_one(&2), 22);
+}
diff --git a/src/test/ui/regions/regions-infer-call-3.rs b/src/test/ui/regions/regions-infer-call-3.rs
new file mode 100644
index 000000000..063ec8428
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-call-3.rs
@@ -0,0 +1,14 @@
+fn select<'r>(x: &'r isize, y: &'r isize) -> &'r isize { x }
+
+fn with<T, F>(f: F) -> T where F: FnOnce(&isize) -> T {
+ f(&20)
+}
+
+fn manip<'a>(x: &'a isize) -> isize {
+ let z = with(|y| { select(x, y) });
+ //~^ ERROR lifetime may not live long enough
+ *z
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-call-3.stderr b/src/test/ui/regions/regions-infer-call-3.stderr
new file mode 100644
index 000000000..ca51555a0
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-call-3.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-call-3.rs:8:24
+ |
+LL | let z = with(|y| { select(x, y) });
+ | -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 isize
+ | has type `&'1 isize`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-call.rs b/src/test/ui/regions/regions-infer-call.rs
new file mode 100644
index 000000000..248f9e923
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-call.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+fn takes_two(x: &isize, y: &isize) -> isize { *x + *y }
+
+fn has_two<'a,'b>(x: &'a isize, y: &'b isize) -> isize {
+ takes_two(x, y)
+}
+
+pub fn main() {
+ assert_eq!(has_two(&20, &2), 22);
+}
diff --git a/src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs
new file mode 100644
index 000000000..fbc0cec56
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs
@@ -0,0 +1,29 @@
+// Test that a type which is contravariant with respect to its region
+// parameter yields an error when used in a covariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+use std::marker;
+
+// This is contravariant with respect to 'a, meaning that
+// Contravariant<'foo> <: Contravariant<'static> because
+// 'foo <= 'static
+struct Contravariant<'a> {
+ marker: marker::PhantomData<&'a()>
+}
+
+fn use_<'short,'long>(c: Contravariant<'short>,
+ s: &'short isize,
+ l: &'long isize,
+ _where:Option<&'short &'long ()>) {
+
+ // Test whether Contravariant<'short> <: Contravariant<'long>. Since
+ // 'short <= 'long, this would be true if the Contravariant type were
+ // covariant with respect to its parameter 'a.
+
+ let _: Contravariant<'long> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr
new file mode 100644
index 000000000..94b80852d
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-contravariance-due-to-decl.rs:25:12
+ |
+LL | fn use_<'short,'long>(c: Contravariant<'short>,
+ | ------ ----- lifetime `'long` defined here
+ | |
+ | lifetime `'short` defined here
+...
+LL | let _: Contravariant<'long> = c;
+ | ^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+ |
+ = help: consider adding the following bound: `'short: 'long`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-contravariance-due-to-ret.rs b/src/test/ui/regions/regions-infer-contravariance-due-to-ret.rs
new file mode 100644
index 000000000..fbd895015
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-contravariance-due-to-ret.rs
@@ -0,0 +1,22 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+
+struct boxed_int<'a> {
+ f: &'a isize,
+}
+
+fn max<'r>(bi: &'r boxed_int, f: &'r isize) -> isize {
+ if *bi.f > *f {*bi.f} else {*f}
+}
+
+fn with(bi: &boxed_int) -> isize {
+ let i = 22;
+ max(bi, &i)
+}
+
+pub fn main() {
+ let g = 21;
+ let foo = boxed_int { f: &g };
+ assert_eq!(with(&foo), 22);
+}
diff --git a/src/test/ui/regions/regions-infer-covariance-due-to-decl.rs b/src/test/ui/regions/regions-infer-covariance-due-to-decl.rs
new file mode 100644
index 000000000..03c0e436e
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-covariance-due-to-decl.rs
@@ -0,0 +1,26 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+use std::marker;
+
+struct Covariant<'a> {
+ marker: marker::PhantomData<fn(&'a ())>
+}
+
+fn use_<'short,'long>(c: Covariant<'long>,
+ s: &'short isize,
+ l: &'long isize,
+ _where:Option<&'short &'long ()>) {
+
+ // Test whether Covariant<'long> <: Covariant<'short>. Since
+ // 'short <= 'long, this would be true if the Covariant type were
+ // contravariant with respect to its parameter 'a.
+
+ let _: Covariant<'short> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr
new file mode 100644
index 000000000..f44a0fad5
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-covariance-due-to-decl.rs:22:12
+ |
+LL | fn use_<'short,'long>(c: Covariant<'long>,
+ | ------ ----- lifetime `'long` defined here
+ | |
+ | lifetime `'short` defined here
+...
+LL | let _: Covariant<'short> = c;
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+ |
+ = help: consider adding the following bound: `'short: 'long`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.rs b/src/test/ui/regions/regions-infer-invariance-due-to-decl.rs
new file mode 100644
index 000000000..102abc0e0
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.rs
@@ -0,0 +1,17 @@
+use std::marker;
+
+struct Invariant<'a> {
+ marker: marker::PhantomData<*mut &'a()>
+}
+
+fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
+ let bj: Invariant<'r> = b_isize;
+}
+
+fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+ b_isize
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr
new file mode 100644
index 000000000..c8c7808e0
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-invariance-due-to-decl.rs:12:5
+ |
+LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+ | -- lifetime `'r` defined here
+LL | b_isize
+ | ^^^^^^^ returning this value requires that `'r` must outlive `'static`
+ |
+ = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs
new file mode 100644
index 000000000..c1fb41bd9
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs
@@ -0,0 +1,15 @@
+struct Invariant<'a> {
+ f: Box<dyn FnOnce(&mut &'a isize) + 'static>,
+}
+
+fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
+ let bj: Invariant<'r> = b_isize;
+}
+
+fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+ b_isize
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr
new file mode 100644
index 000000000..1165011c1
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:10:5
+ |
+LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+ | -- lifetime `'r` defined here
+LL | b_isize
+ | ^^^^^^^ returning this value requires that `'r` must outlive `'static`
+ |
+ = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs
new file mode 100644
index 000000000..1078f77a0
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs
@@ -0,0 +1,15 @@
+struct Invariant<'a> {
+ f: Box<dyn FnOnce() -> *mut &'a isize + 'static>,
+}
+
+fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
+ let bj: Invariant<'r> = b_isize;
+}
+
+fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+ b_isize
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr
new file mode 100644
index 000000000..f3973a93b
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:10:5
+ |
+LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+ | -- lifetime `'r` defined here
+LL | b_isize
+ | ^^^^^^^ returning this value requires that `'r` must outlive `'static`
+ |
+ = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-not-param.rs b/src/test/ui/regions/regions-infer-not-param.rs
new file mode 100644
index 000000000..c3766bce1
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-not-param.rs
@@ -0,0 +1,24 @@
+struct Direct<'a> {
+ f: &'a isize
+}
+
+struct Indirect1 {
+ // Here the lifetime parameter of direct is bound by the fn()
+ g: Box<dyn FnOnce(Direct) + 'static>
+}
+
+struct Indirect2<'a> {
+ // But here it is set to 'a
+ g: Box<dyn FnOnce(Direct<'a>) + 'static>
+}
+
+fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
+//~^ ERROR lifetime may not live long enough
+
+fn take_indirect1(p: Indirect1) -> Indirect1 { p }
+
+fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+//~^ ERROR lifetime may not live long enough
+//~| ERROR lifetime may not live long enough
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-not-param.stderr b/src/test/ui/regions/regions-infer-not-param.stderr
new file mode 100644
index 000000000..d12f07a77
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-not-param.stderr
@@ -0,0 +1,40 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-not-param.rs:15:54
+ |
+LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
+ | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ | |
+ | lifetime `'a` defined here
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-not-param.rs:20:63
+ |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+ | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+ | |
+ | lifetime `'a` defined here
+ |
+ = help: consider adding the following bound: `'b: 'a`
+ = note: requirement occurs because of the type `Indirect2<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Indirect2<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-not-param.rs:20:63
+ |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+ | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ | |
+ | lifetime `'a` defined here
+ |
+ = help: consider adding the following bound: `'a: 'b`
+ = note: requirement occurs because of the type `Indirect2<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Indirect2<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'b` and `'a` must be the same: replace one with the other
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.rs b/src/test/ui/regions/regions-infer-paramd-indirect.rs
new file mode 100644
index 000000000..978c84e53
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-paramd-indirect.rs
@@ -0,0 +1,27 @@
+// Check that we correctly infer that b and c must be region
+// parameterized because they reference a which requires a region.
+
+type A<'a> = &'a isize;
+type B<'a> = Box<A<'a>>;
+
+struct C<'a> {
+ f: Box<B<'a>>
+}
+
+trait SetF<'a> {
+ fn set_f_ok(&mut self, b: Box<B<'a>>);
+ fn set_f_bad(&mut self, b: Box<B>);
+}
+
+impl<'a> SetF<'a> for C<'a> {
+ fn set_f_ok(&mut self, b: Box<B<'a>>) {
+ self.f = b;
+ }
+
+ fn set_f_bad(&mut self, b: Box<B>) {
+ self.f = b;
+ //~^ ERROR lifetime may not live long enough
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.stderr
new file mode 100644
index 000000000..afabdc1de
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-paramd-indirect.stderr
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-infer-paramd-indirect.rs:22:9
+ |
+LL | impl<'a> SetF<'a> for C<'a> {
+ | -- lifetime `'a` defined here
+...
+LL | fn set_f_bad(&mut self, b: Box<B>) {
+ | - has type `Box<Box<&'1 isize>>`
+LL | self.f = b;
+ | ^^^^^^ assignment requires that `'1` must outlive `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-infer-proc-static-upvar.rs b/src/test/ui/regions/regions-infer-proc-static-upvar.rs
new file mode 100644
index 000000000..5a64aa734
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-proc-static-upvar.rs
@@ -0,0 +1,24 @@
+// Test that, when a variable of type `&T` is captured inside a proc,
+// we correctly infer/require that its lifetime is 'static.
+
+fn foo<F:FnOnce()+'static>(_p: F) { }
+
+static i: isize = 3;
+
+fn capture_local() {
+ let x = 3;
+ let y = &x; //~ ERROR `x` does not live long enough
+ foo(move|| {
+ let _a = *y;
+ });
+}
+
+fn capture_static() {
+ // Legal because &i can have static lifetime:
+ let y = &i;
+ foo(move|| {
+ let _a = *y;
+ });
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-infer-proc-static-upvar.stderr b/src/test/ui/regions/regions-infer-proc-static-upvar.stderr
new file mode 100644
index 000000000..803d0d744
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-proc-static-upvar.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+ --> $DIR/regions-infer-proc-static-upvar.rs:10:13
+ |
+LL | let y = &x;
+ | ^^ borrowed value does not live long enough
+LL | / foo(move|| {
+LL | | let _a = *y;
+LL | | });
+ | |______- argument requires that `x` is borrowed for `'static`
+LL | }
+ | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs b/src/test/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs
new file mode 100644
index 000000000..31a48b4ad
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(dead_code)]
+// Test an edge case in region inference: the lifetime of the borrow
+// of `*x` must be extended to at least 'a.
+
+// pretty-expanded FIXME #23616
+
+fn foo<'a,'b>(x: &'a &'b mut isize) -> &'a isize {
+ let y = &*x; // should be inferred to have type &'a &'b mut isize...
+
+ // ...because if we inferred, say, &'x &'b mut isize where 'x <= 'a,
+ // this reborrow would be illegal:
+ &**y
+}
+
+pub fn main() {
+ /* Just want to know that it compiles. */
+}
diff --git a/src/test/ui/regions/regions-infer-region-in-fn-but-not-type.rs b/src/test/ui/regions/regions-infer-region-in-fn-but-not-type.rs
new file mode 100644
index 000000000..6aa5d8217
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-region-in-fn-but-not-type.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_camel_case_types)]
+
+
+// check that the &isize here does not cause us to think that `foo`
+// contains region pointers
+// pretty-expanded FIXME #23616
+
+struct foo(Box<dyn FnMut(&isize)+'static>);
+
+fn take_foo<T:'static>(x: T) {}
+
+fn have_foo(f: foo) {
+ take_foo(f);
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-static-from-proc.rs b/src/test/ui/regions/regions-infer-static-from-proc.rs
new file mode 100644
index 000000000..39501e2d6
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-static-from-proc.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(non_upper_case_globals)]
+
+// Check that the 'static bound on a proc influences lifetimes of
+// region variables contained within (otherwise, region inference will
+// give `x` a very short lifetime).
+
+// pretty-expanded FIXME #23616
+
+static i: usize = 3;
+fn foo<F:FnOnce()+'static>(_: F) {}
+fn read(_: usize) { }
+pub fn main() {
+ let x = &i;
+ foo(move|| {
+ read(*x);
+ });
+}
diff --git a/src/test/ui/regions/regions-issue-21422.rs b/src/test/ui/regions/regions-issue-21422.rs
new file mode 100644
index 000000000..198b71466
--- /dev/null
+++ b/src/test/ui/regions/regions-issue-21422.rs
@@ -0,0 +1,18 @@
+// run-pass
+// Regression test for issue #21422, which was related to failing to
+// add inference constraints that the operands of a binary operator
+// should outlive the binary operation itself.
+
+// pretty-expanded FIXME #23616
+
+pub struct P<'a> {
+ _ptr: *const &'a u8,
+}
+
+impl <'a> PartialEq for P<'a> {
+ fn eq(&self, other: &P<'a>) -> bool {
+ (self as *const _) == (other as *const _)
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-issue-22246.rs b/src/test/ui/regions/regions-issue-22246.rs
new file mode 100644
index 000000000..085883367
--- /dev/null
+++ b/src/test/ui/regions/regions-issue-22246.rs
@@ -0,0 +1,29 @@
+// run-pass
+#![allow(unused_imports)]
+// Regression test for issue #22246 -- we should be able to deduce
+// that `&'a B::Owned` implies that `B::Owned : 'a`.
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+use std::ops::Deref;
+
+pub trait ToOwned: Sized {
+ type Owned: Borrow<Self>;
+ fn to_owned(&self) -> Self::Owned;
+}
+
+pub trait Borrow<Borrowed> {
+ fn borrow(&self) -> &Borrowed;
+}
+
+pub struct Foo<B:ToOwned> {
+ owned: B::Owned
+}
+
+fn foo<B:ToOwned>(this: &Foo<B>) -> &B {
+ this.owned.borrow()
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs
new file mode 100644
index 000000000..177f52fa7
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs
@@ -0,0 +1,30 @@
+fn a<'a, 'b:'a>(x: &mut &'a isize, y: &mut &'b isize) {
+ // Note: this is legal because of the `'b:'a` declaration.
+ *x = *y;
+}
+
+fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
+ // Illegal now because there is no `'b:'a` declaration.
+ *x = *y;
+}
+
+fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
+ // Here we try to call `foo` but do not know that `'a` and `'b` are
+ // related as required.
+ a(x, y);
+}
+
+fn d() {
+ // 'a and 'b are early bound in the function `a` because they appear
+ // inconstraints:
+ let _: fn(&mut &isize, &mut &isize) = a;
+ //~^ ERROR mismatched types [E0308]
+}
+
+fn e() {
+ // 'a and 'b are late bound in the function `b` because there are
+ // no constraints:
+ let _: fn(&mut &isize, &mut &isize) = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
new file mode 100644
index 000000000..a0daf58c6
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43
+ |
+LL | let _: fn(&mut &isize, &mut &isize) = a;
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
+ found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs b/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs
new file mode 100644
index 000000000..3852a14d9
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs
@@ -0,0 +1,33 @@
+// run-pass
+// This is a regression test for the ICE from issue #10846.
+//
+// The original issue causing the ICE: the LUB-computations during
+// type inference were encountering late-bound lifetimes, and
+// asserting that such lifetimes should have already been substituted
+// with a concrete lifetime.
+//
+// However, those encounters were occurring within the lexical scope
+// of the binding for the late-bound lifetime; that is, the late-bound
+// lifetimes were perfectly valid. The core problem was that the type
+// folding code was over-zealously passing back all lifetimes when
+// doing region-folding, when really all clients of the region-folding
+// case only want to see FREE lifetime variables, not bound ones.
+
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+ fn explicit() {
+ fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<dyn for<'a> FnMut(&'a isize)>) {}
+ test(Some(Box::new(|_f: Box<dyn for<'a> FnMut(&'a isize)>| {})));
+ }
+
+ // The code below is shorthand for the code above (and more likely
+ // to represent what one encounters in practice).
+ fn implicit() {
+ fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<dyn FnMut(& isize)>) {}
+ test(Some(Box::new(|_f: Box<dyn FnMut(& isize)>| {})));
+ }
+
+ explicit();
+ implicit();
+}
diff --git a/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs
new file mode 100644
index 000000000..1b25294c7
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs
@@ -0,0 +1,26 @@
+// This tests verifies that unary structs and enum variants
+// are treated as rvalues and their lifetime is not bounded to
+// the static scope.
+
+fn id<T>(x: T) -> T { x }
+
+struct Test;
+
+enum MyEnum {
+ Variant1
+}
+
+fn structLifetime<'a>() -> &'a Test {
+ let testValue = &id(Test);
+ testValue
+ //~^ ERROR cannot return value referencing temporary value
+}
+
+fn variantLifetime<'a>() -> &'a MyEnum {
+ let testValue = &id(MyEnum::Variant1);
+ testValue
+ //~^ ERROR cannot return value referencing temporary value
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr
new file mode 100644
index 000000000..b4bf2ab31
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr
@@ -0,0 +1,19 @@
+error[E0515]: cannot return value referencing temporary value
+ --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:15:3
+ |
+LL | let testValue = &id(Test);
+ | -------- temporary value created here
+LL | testValue
+ | ^^^^^^^^^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+ --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:21:3
+ |
+LL | let testValue = &id(MyEnum::Variant1);
+ | -------------------- temporary value created here
+LL | testValue
+ | ^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs b/src/test/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs
new file mode 100644
index 000000000..b6a89e29e
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![allow(dead_code)]
+// This test verifies that temporary lifetime is correctly computed
+// for static objects in enclosing scopes.
+
+
+use std::cmp::PartialEq;
+
+fn f<T:PartialEq+std::fmt::Debug>(o: &mut Option<T>) {
+ assert_eq!(*o, None);
+}
+
+pub fn main() {
+ mod t {
+ enum E {V=1, A=0}
+ static C: E = E::V;
+ }
+
+ f::<isize>(&mut None);
+}
diff --git a/src/test/ui/regions/regions-link-fn-args.rs b/src/test/ui/regions/regions-link-fn-args.rs
new file mode 100644
index 000000000..231407b22
--- /dev/null
+++ b/src/test/ui/regions/regions-link-fn-args.rs
@@ -0,0 +1,15 @@
+// run-pass
+// Test that region inference correctly links up the regions when a
+// `ref` borrow occurs inside a fn argument.
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+fn with<'a, F>(_: F) where F: FnOnce(&'a Vec<isize>) -> &'a Vec<isize> { }
+
+fn foo() {
+ with(|&ref ints| ints);
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-lub-ref-ref-rc.rs b/src/test/ui/regions/regions-lub-ref-ref-rc.rs
new file mode 100644
index 000000000..96c71b084
--- /dev/null
+++ b/src/test/ui/regions/regions-lub-ref-ref-rc.rs
@@ -0,0 +1,28 @@
+// run-pass
+#![allow(dead_code)]
+// Test a corner case of LUB coercion. In this case, one arm of the
+// match requires a deref coercion and the other doesn't, and there
+// is an extra `&` on the `rc`. We want to be sure that the lifetime
+// assigned to this `&rc` value is not `'a` but something smaller. In
+// other words, the type from `rc` is `&'a Rc<String>` and the type
+// from `&rc` should be `&'x &'a Rc<String>`, where `'x` is something
+// small.
+
+use std::rc::Rc;
+
+#[derive(Clone)]
+enum Cached<'mir> {
+ Ref(&'mir String),
+ Owned(Rc<String>),
+}
+
+impl<'mir> Cached<'mir> {
+ fn get_ref<'a>(&'a self) -> &'a String {
+ match *self {
+ Cached::Ref(r) => r,
+ Cached::Owned(ref rc) => &rc,
+ }
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-mock-codegen.rs b/src/test/ui/regions/regions-mock-codegen.rs
new file mode 100644
index 000000000..9d0ca76e4
--- /dev/null
+++ b/src/test/ui/regions/regions-mock-codegen.rs
@@ -0,0 +1,54 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+// pretty-expanded FIXME #23616
+#![feature(allocator_api)]
+
+use std::alloc::{handle_alloc_error, Allocator, Global, Layout};
+use std::ptr::NonNull;
+
+struct arena(());
+
+struct Bcx<'a> {
+ fcx: &'a Fcx<'a>,
+}
+
+struct Fcx<'a> {
+ arena: &'a arena,
+ ccx: &'a Ccx,
+}
+
+struct Ccx {
+ x: isize,
+}
+
+fn allocate(_bcx: &arena) -> &Bcx<'_> {
+ unsafe {
+ let layout = Layout::new::<Bcx>();
+ let ptr = Global.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+ &*(ptr.as_ptr() as *const _)
+ }
+}
+
+fn h<'a>(bcx: &'a Bcx<'a>) -> &'a Bcx<'a> {
+ return allocate(bcx.fcx.arena);
+}
+
+fn g(fcx: &Fcx) {
+ let bcx = Bcx { fcx };
+ let bcx2 = h(&bcx);
+ unsafe {
+ Global.deallocate(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::<Bcx>());
+ }
+}
+
+fn f(ccx: &Ccx) {
+ let a = arena(());
+ let fcx = Fcx { arena: &a, ccx };
+ return g(&fcx);
+}
+
+pub fn main() {
+ let ccx = Ccx { x: 0 };
+ f(&ccx);
+}
diff --git a/src/test/ui/regions/regions-name-duplicated.rs b/src/test/ui/regions/regions-name-duplicated.rs
new file mode 100644
index 000000000..f6616591a
--- /dev/null
+++ b/src/test/ui/regions/regions-name-duplicated.rs
@@ -0,0 +1,6 @@
+struct Foo<'a, 'a> {
+ //~^ ERROR the name `'a` is already used for a generic parameter
+ x: &'a isize,
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-name-duplicated.stderr b/src/test/ui/regions/regions-name-duplicated.stderr
new file mode 100644
index 000000000..cef73c18d
--- /dev/null
+++ b/src/test/ui/regions/regions-name-duplicated.stderr
@@ -0,0 +1,11 @@
+error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/regions-name-duplicated.rs:1:16
+ |
+LL | struct Foo<'a, 'a> {
+ | -- ^^ already used
+ | |
+ | first use of `'a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/regions/regions-name-static.rs b/src/test/ui/regions/regions-name-static.rs
new file mode 100644
index 000000000..da316c6ef
--- /dev/null
+++ b/src/test/ui/regions/regions-name-static.rs
@@ -0,0 +1,6 @@
+struct Foo<'static> {
+ //~^ ERROR invalid lifetime parameter name: `'static`
+ x: &'static isize,
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-name-static.stderr b/src/test/ui/regions/regions-name-static.stderr
new file mode 100644
index 000000000..4b7026e65
--- /dev/null
+++ b/src/test/ui/regions/regions-name-static.stderr
@@ -0,0 +1,9 @@
+error[E0262]: invalid lifetime parameter name: `'static`
+ --> $DIR/regions-name-static.rs:1:12
+ |
+LL | struct Foo<'static> {
+ | ^^^^^^^ 'static is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0262`.
diff --git a/src/test/ui/regions/regions-name-undeclared.rs b/src/test/ui/regions/regions-name-undeclared.rs
new file mode 100644
index 000000000..7b6ede193
--- /dev/null
+++ b/src/test/ui/regions/regions-name-undeclared.rs
@@ -0,0 +1,58 @@
+// edition:2018
+// Check that lifetime resolver enforces the lifetime name scoping
+// rules correctly in various scenarios.
+
+struct Foo<'a> {
+ x: &'a isize
+}
+
+impl<'a> Foo<'a> {
+ // &'a is inherited:
+ fn m1(&self, arg: &'a isize) { }
+ fn m2(&'a self) { }
+ fn m3(&self, arg: Foo<'a>) { }
+
+ // &'b is not:
+ fn m4(&self, arg: &'b isize) { } //~ ERROR undeclared lifetime
+ fn m5(&'b self) { } //~ ERROR undeclared lifetime
+ fn m6(&self, arg: Foo<'b>) { } //~ ERROR undeclared lifetime
+}
+
+fn bar<'a>(x: &'a isize) {
+ // &'a is visible to code:
+ let y: &'a isize = x;
+
+ // &'a is not visible to *items*:
+ type X = Option<&'a isize>; //~ ERROR can't use generic parameters from outer item
+ enum E {
+ E1(&'a isize) //~ ERROR can't use generic parameters from outer item
+ }
+ struct S {
+ f: &'a isize //~ ERROR can't use generic parameters from outer item
+ }
+ fn f(a: &'a isize) { } //~ ERROR can't use generic parameters from outer item
+
+ // &'a CAN be declared on functions and used then:
+ fn g<'a>(a: &'a isize) { } // OK
+ fn h(a: Box<dyn for<'a> FnOnce(&'a isize)>) { } // OK
+}
+
+// Test nesting of lifetimes in fn type declarations
+fn fn_types(a: &'a isize, //~ ERROR undeclared lifetime
+ b: Box<dyn for<'a> FnOnce(&'a isize,
+ &'b isize, //~ ERROR undeclared lifetime
+ Box<dyn for<'b> FnOnce(&'a isize,
+ &'b isize)>,
+ &'b isize)>, //~ ERROR undeclared lifetime
+ c: &'a isize) //~ ERROR undeclared lifetime
+{
+}
+
+struct Bug {}
+impl Bug {
+ async fn buggy(&self) -> &'a str { //~ ERROR use of undeclared lifetime name `'a`
+ todo!()
+ }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr
new file mode 100644
index 000000000..532603de5
--- /dev/null
+++ b/src/test/ui/regions/regions-name-undeclared.stderr
@@ -0,0 +1,156 @@
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/regions-name-undeclared.rs:16:24
+ |
+LL | fn m4(&self, arg: &'b isize) { }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'b` here
+ |
+LL | fn m4<'b>(&self, arg: &'b isize) { }
+ | ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b, 'a> Foo<'a> {
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/regions-name-undeclared.rs:17:12
+ |
+LL | fn m5(&'b self) { }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'b` here
+ |
+LL | fn m5<'b>(&'b self) { }
+ | ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b, 'a> Foo<'a> {
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/regions-name-undeclared.rs:18:27
+ |
+LL | fn m6(&self, arg: Foo<'b>) { }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'b` here
+ |
+LL | fn m6<'b>(&self, arg: Foo<'b>) { }
+ | ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b, 'a> Foo<'a> {
+ | +++
+
+error[E0401]: can't use generic parameters from outer item
+ --> $DIR/regions-name-undeclared.rs:26:22
+ |
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
+LL | type X = Option<&'a isize>;
+ | - ^^ use of generic parameter from outer item
+ | |
+ | help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0401]: can't use generic parameters from outer item
+ --> $DIR/regions-name-undeclared.rs:28:13
+ |
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
+LL | enum E {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | E1(&'a isize)
+ | ^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
+ --> $DIR/regions-name-undeclared.rs:31:13
+ |
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
+LL | struct S {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | f: &'a isize
+ | ^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
+ --> $DIR/regions-name-undeclared.rs:33:14
+ |
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
+LL | fn f(a: &'a isize) { }
+ | - ^^ use of generic parameter from outer item
+ | |
+ | help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-name-undeclared.rs:41:17
+ |
+LL | fn fn_types(a: &'a isize,
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/regions-name-undeclared.rs:43:36
+ |
+LL | ... &'b isize,
+ | ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
+ | +++
+help: consider introducing lifetime `'b` here
+ |
+LL | fn fn_types<'b>(a: &'a isize,
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/regions-name-undeclared.rs:46:36
+ |
+LL | ... &'b isize)>,
+ | ^^ undeclared lifetime
+ |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
+ | +++
+help: consider introducing lifetime `'b` here
+ |
+LL | fn fn_types<'b>(a: &'a isize,
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-name-undeclared.rs:47:17
+ |
+LL | fn fn_types(a: &'a isize,
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+...
+LL | c: &'a isize)
+ | ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-name-undeclared.rs:53:31
+ |
+LL | async fn buggy(&self) -> &'a str {
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | async fn buggy<'a>(&self) -> &'a str {
+ | ++++
+help: consider introducing lifetime `'a` here
+ |
+LL | impl<'a> Bug {
+ | ++++
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0261, E0401.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-nested-fns-2.rs b/src/test/ui/regions/regions-nested-fns-2.rs
new file mode 100644
index 000000000..3b3e26c45
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns-2.rs
@@ -0,0 +1,12 @@
+fn ignore<F>(_f: F) where F: for<'z> FnOnce(&'z isize) -> &'z isize {}
+
+fn nested() {
+ let y = 3;
+ ignore(
+ |z| {
+ if false { &y } else { z }
+ //~^ ERROR `y` does not live long enough
+ });
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-nested-fns-2.stderr b/src/test/ui/regions/regions-nested-fns-2.stderr
new file mode 100644
index 000000000..43c8d1272
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns-2.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `y` does not live long enough
+ --> $DIR/regions-nested-fns-2.rs:7:25
+ |
+LL | |z| {
+ | --- value captured here
+LL | if false { &y } else { z }
+ | -^
+ | ||
+ | |borrowed value does not live long enough
+ | returning this value requires that `y` is borrowed for `'static`
+...
+LL | }
+ | - `y` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-nested-fns.rs b/src/test/ui/regions/regions-nested-fns.rs
new file mode 100644
index 000000000..d9698ced3
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns.rs
@@ -0,0 +1,24 @@
+fn ignore<T>(t: T) {}
+
+fn nested<'x>(x: &'x isize) {
+ let y = 3;
+ let mut ay = &y;
+ //~^ ERROR `y` does not live long enough [E0597]
+
+ ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ ay = x;
+ ay = &y;
+ //~^ ERROR `y` does not live long enough
+ ay = z;
+ //~^ ERROR borrowed data escapes outside of closure [E0521]
+ }));
+
+ ignore::< Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ if false { return x; }
+ //~^ ERROR lifetime may not live long enough
+ if false { return ay; }
+ return z;
+ }));
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr
new file mode 100644
index 000000000..bb2740310
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns.stderr
@@ -0,0 +1,52 @@
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/regions-nested-fns.rs:12:9
+ |
+LL | let mut ay = &y;
+ | ------ `ay` declared here, outside of the closure body
+...
+LL | ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ | - `z` is a reference that is only valid in the closure body
+...
+LL | ay = z;
+ | ^^^^^^ `z` escapes the closure body here
+
+error[E0597]: `y` does not live long enough
+ --> $DIR/regions-nested-fns.rs:5:18
+ |
+LL | let mut ay = &y;
+ | ^^ borrowed value does not live long enough
+...
+LL | if false { return ay; }
+ | -- returning this value requires that `y` is borrowed for `'static`
+...
+LL | }
+ | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+ --> $DIR/regions-nested-fns.rs:10:15
+ |
+LL | ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ | --- value captured here
+LL | ay = x;
+LL | ay = &y;
+ | ^ borrowed value does not live long enough
+...
+LL | if false { return ay; }
+ | -- returning this value requires that `y` is borrowed for `'static`
+...
+LL | }
+ | - `y` dropped here while still borrowed
+
+error: lifetime may not live long enough
+ --> $DIR/regions-nested-fns.rs:17:27
+ |
+LL | fn nested<'x>(x: &'x isize) {
+ | -- lifetime `'x` defined here
+...
+LL | if false { return x; }
+ | ^ returning this value requires that `'x` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0521, E0597.
+For more information about an error, try `rustc --explain E0521`.
diff --git a/src/test/ui/regions/regions-no-bound-in-argument-cleanup.rs b/src/test/ui/regions/regions-no-bound-in-argument-cleanup.rs
new file mode 100644
index 000000000..aafab5d86
--- /dev/null
+++ b/src/test/ui/regions/regions-no-bound-in-argument-cleanup.rs
@@ -0,0 +1,24 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+use std::marker;
+
+pub struct Foo<T>(marker::PhantomData<T>);
+
+impl<T> Iterator for Foo<T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<T> {
+ None
+ }
+}
+
+impl<T> Drop for Foo<T> {
+ fn drop(&mut self) {
+ self.next();
+ }
+}
+
+pub fn foo<'a>(_: Foo<&'a ()>) {}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-no-variance-from-fn-generics.rs b/src/test/ui/regions/regions-no-variance-from-fn-generics.rs
new file mode 100644
index 000000000..76706a827
--- /dev/null
+++ b/src/test/ui/regions/regions-no-variance-from-fn-generics.rs
@@ -0,0 +1,44 @@
+// run-pass
+#![allow(unused_variables)]
+// Issue #12856: a lifetime formal binding introduced by a generic fn
+// should not upset the variance inference for actual occurrences of
+// that lifetime in type expressions.
+
+
+pub trait HasLife<'a> {
+ fn dummy(&'a self) { } // just to induce a variance on 'a
+}
+
+trait UseLife01 {
+ fn refs<'a, H: HasLife<'a>>(&'a self) -> H;
+}
+
+trait UseLife02 {
+ fn refs<'a, T: 'a, H: HasType<&'a T>>(&'a self) -> H;
+}
+
+
+pub trait HasType<T>
+{
+ fn dummy(&self, t: T) -> T { panic!() }
+}
+
+
+trait UseLife03<T> {
+ fn refs<'a, H: HasType<&'a T>>(&'a self) -> H where T: 'a;
+}
+
+
+// (The functions below were not actually a problem observed during
+// fixing of #12856; they just seem like natural tests to put in to
+// cover a couple more points in the testing space)
+
+pub fn top_refs_1<'a, H: HasLife<'a>>(_s: &'a ()) -> H {
+ unimplemented!()
+}
+
+pub fn top_refs_2<'a, T: 'a, H: HasType<&'a T>>(_s: &'a ()) -> H {
+ unimplemented!()
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
new file mode 100644
index 000000000..389f82e79
--- /dev/null
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
@@ -0,0 +1,31 @@
+// Test that we are able to normalize in the list of where-clauses,
+// even if `'a: 'b` is required.
+
+trait Project<'a, 'b> {
+ type Item;
+}
+
+impl<'a, 'b> Project<'a, 'b> for ()
+where
+ 'a: 'b,
+{
+ type Item = ();
+}
+
+// No error here, we have 'a: 'b. We used to report an error here
+// though, see https://github.com/rust-lang/rust/issues/45937.
+fn foo<'a: 'b, 'b>()
+where
+ <() as Project<'a, 'b>>::Item: Eq,
+{
+}
+
+// Here we get an error: we need `'a: 'b`.
+fn bar<'a, 'b>()
+//~^ ERROR cannot infer
+where
+ <() as Project<'a, 'b>>::Item: Eq,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
new file mode 100644
index 000000000..567283729
--- /dev/null
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -0,0 +1,27 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
+ |
+LL | fn bar<'a, 'b>()
+ | ^^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
+ |
+LL | fn bar<'a, 'b>()
+ | ^^
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined here...
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
+ |
+LL | fn bar<'a, 'b>()
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
+ |
+LL | fn bar<'a, 'b>()
+ | ^^^
+ = note: expected `Project<'a, 'b>`
+ found `Project<'_, '_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-nullary-variant.rs b/src/test/ui/regions/regions-nullary-variant.rs
new file mode 100644
index 000000000..82470af82
--- /dev/null
+++ b/src/test/ui/regions/regions-nullary-variant.rs
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+enum roption<'a> {
+ a, b(&'a usize)
+}
+
+fn mk(cond: bool, ptr: &usize) -> roption {
+ if cond {roption::a} else {roption::b(ptr)}
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
new file mode 100644
index 000000000..15deaba56
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod rev_variant_struct_region {
+ struct Foo<'a> {
+ x: fn(&'a i32),
+ }
+ enum Bar<'a,'b> {
+ V(&'a Foo<'b>)
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
new file mode 100644
index 000000000..7767c13c8
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_region {
+ struct Foo<'a> {
+ x: &'a i32,
+ }
+ enum Bar<'a,'b> {
+ V(&'a Foo<'b>)
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
new file mode 100644
index 000000000..374159942
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_type {
+ struct Foo<T> {
+ x: fn(T)
+ }
+ enum Bar<'a,'b> {
+ V(&'a Foo<&'b i32>)
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
new file mode 100644
index 000000000..2e7f198d8
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_type {
+ struct Foo<T> {
+ x: T
+ }
+ enum Bar<'a,'b> {
+ V(&'a Foo<&'b i32>)
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
new file mode 100644
index 000000000..45155c721
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod rev_variant_struct_region {
+ struct Foo<'a> {
+ x: fn(&'a i32),
+ }
+ struct Bar<'a,'b> {
+ f: &'a Foo<'b>
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
new file mode 100644
index 000000000..bba8b2445
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_region {
+ struct Foo<'a> {
+ x: &'a i32,
+ }
+ struct Bar<'a,'b> {
+ f: &'a Foo<'b>
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
new file mode 100644
index 000000000..220d2e83c
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod rev_variant_struct_type {
+ struct Foo<T> {
+ x: fn(T)
+ }
+ struct Bar<'a,'b> {
+ f: &'a Foo<&'b i32>
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
new file mode 100644
index 000000000..9ddcdb649
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_type {
+ struct Foo<T> {
+ x: T
+ }
+ struct Bar<'a,'b> {
+ f: &'a Foo<&'b i32>
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
new file mode 100644
index 000000000..152eed5ac
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
@@ -0,0 +1,52 @@
+// Test that structs with higher-ranked where clauses don't generate
+// "outlives" requirements. Issue #22246.
+
+#![allow(dead_code)]
+
+pub trait TheTrait<'b> {
+ type TheAssocType;
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'a,'b> TheTrait<'a> for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+pub struct WithHrAssoc<T>
+ where for<'a> T : TheTrait<'a>
+{
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // We get an error because 'b:'a does not hold:
+
+ let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+ //~^ ERROR lifetime may not live long enough
+}
+
+pub trait TheSubTrait : for<'a> TheTrait<'a> {
+}
+
+impl<'b> TheSubTrait for TheType<'b> { }
+
+pub struct WithHrAssocSub<T>
+ where T : TheSubTrait
+{
+ m: [T; 0]
+}
+
+fn with_assoc_sub<'a,'b>() {
+ // The error here is just because `'b:'a` must hold for the type
+ // below to be well-formed, it is not related to the HR relation.
+
+ let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+ //~^ ERROR lifetime may not live long enough
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr
new file mode 100644
index 000000000..187e9056e
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:27:12
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:46:12
+ |
+LL | fn with_assoc_sub<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs
new file mode 100644
index 000000000..4fda7774b
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs
@@ -0,0 +1,35 @@
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears, even when the
+// constraint is in a where clause not a bound. Issue #22246.
+
+#![allow(dead_code)]
+
+pub trait TheTrait {
+ type TheAssocType;
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+pub struct WithAssoc<T> where T : TheTrait {
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a.
+
+ let _: &'a WithAssoc<TheType<'b>> = loop { };
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr
new file mode 100644
index 000000000..4178e951c
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container-wc.rs:30:12
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-outlives-projection-container.rs b/src/test/ui/regions/regions-outlives-projection-container.rs
new file mode 100644
index 000000000..7b9829cf8
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container.rs
@@ -0,0 +1,77 @@
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears. Issue #22246.
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+pub trait TheTrait {
+ type TheAssocType;
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+pub struct WithAssoc<T:TheTrait> {
+ m: [T; 0]
+}
+
+pub struct WithoutAssoc<T> {
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a.
+
+ // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
+ // `_x` is changed to `_`
+ let _x: &'a WithAssoc<TheType<'b>> = loop { };
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn with_assoc1<'a,'b>() where 'b : 'a {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a, so 'b : 'a must hold, and
+ // that is in the where clauses, so we're fine.
+
+ let _x: &'a WithAssoc<TheType<'b>> = loop { };
+}
+
+fn without_assoc<'a,'b>() {
+ // Here there are no associated types but there is a requirement
+ // that `'b:'a` holds because the `'b` appears in `TheType<'b>`.
+
+ let _x: &'a WithoutAssoc<TheType<'b>> = loop { };
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn call_with_assoc<'a,'b>() {
+ // As `with_assoc`, but just checking that we impose the same rule
+ // on the value supplied for the type argument, even when there is
+ // no data.
+
+ call::<&'a WithAssoc<TheType<'b>>>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn call_without_assoc<'a,'b>() {
+ // As `without_assoc`, but in a distinct scenario.
+
+ call::<&'a WithoutAssoc<TheType<'b>>>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn call<T>() { }
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr
new file mode 100644
index 000000000..073a31900
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container.stderr
@@ -0,0 +1,54 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container.rs:36:13
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container.rs:54:13
+ |
+LL | fn without_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _x: &'a WithoutAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container.rs:63:5
+ |
+LL | fn call_with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | call::<&'a WithAssoc<TheType<'b>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container.rs:70:5
+ |
+LL | fn call_without_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | call::<&'a WithoutAssoc<TheType<'b>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/regions/regions-outlives-projection-hrtype.rs b/src/test/ui/regions/regions-outlives-projection-hrtype.rs
new file mode 100644
index 000000000..5f9700df1
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-hrtype.rs
@@ -0,0 +1,26 @@
+// Test for the outlives relation when applied to a projection on a
+// type with bound regions. In this case, we are checking that
+// `<for<'r> fn(&'r T) as TheTrait>::TheType: 'a` If we're not
+// careful, we could wind up with a constraint that `'r:'a`, but since
+// `'r` is bound, that leads to badness. This test checks that
+// everything works.
+
+// check-pass
+#![allow(dead_code)]
+
+trait TheTrait {
+ type TheType;
+}
+
+fn wf<T>() { }
+
+type FnType<T> = for<'r> fn(&'r T);
+
+fn foo<'a,'b,T>()
+ where FnType<T>: TheTrait
+{
+ wf::< <FnType<T> as TheTrait>::TheType >();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-projection-trait-def.rs b/src/test/ui/regions/regions-outlives-projection-trait-def.rs
new file mode 100644
index 000000000..5c37a585a
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-trait-def.rs
@@ -0,0 +1,21 @@
+// Test that `<F as Foo<'a>>::Type: 'b`, where `trait Foo<'a> { Type:
+// 'a; }`, does not require that `F: 'b`.
+
+// check-pass
+#![allow(dead_code)]
+
+trait SomeTrait<'a> {
+ type Type: 'a;
+}
+
+impl<'a: 'c, 'c, T> SomeTrait<'a> for &'c T where T: SomeTrait<'a> {
+ type Type = <T as SomeTrait<'a>>::Type;
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // |
+ // Note that this type must outlive 'a, due to the trait
+ // definition. If we fall back to OutlivesProjectionComponents
+ // here, then we would require that `T:'a`, which is too strong.
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-scalar.rs b/src/test/ui/regions/regions-outlives-scalar.rs
new file mode 100644
index 000000000..ce34ffcc8
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-scalar.rs
@@ -0,0 +1,13 @@
+// Test that scalar values outlive all regions.
+// Rule OutlivesScalar from RFC 1214.
+
+// check-pass
+#![allow(dead_code)]
+
+struct Foo<'a> {
+ x: &'a i32,
+ y: &'static i32
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-params.rs b/src/test/ui/regions/regions-params.rs
new file mode 100644
index 000000000..04f3b8eaf
--- /dev/null
+++ b/src/test/ui/regions/regions-params.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(unused_parens)]
+
+
+fn region_identity(x: &usize) -> &usize { x }
+
+fn apply<T, F>(t: T, f: F) -> T where F: FnOnce(T) -> T { f(t) }
+
+fn parameterized(x: &usize) -> usize {
+ let z = apply(x, ({|y|
+ region_identity(y)
+ }));
+ *z
+}
+
+pub fn main() {
+ let x = 3;
+ assert_eq!(parameterized(&x), 3);
+}
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19552.rs b/src/test/ui/regions/regions-pattern-typing-issue-19552.rs
new file mode 100644
index 000000000..a64ab1c85
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19552.rs
@@ -0,0 +1,8 @@
+fn assert_static<T: 'static>(_t: T) {}
+
+fn main() {
+ let line = String::new();
+ match [&*line] { //~ ERROR `line` does not live long enough
+ [ word ] => { assert_static(word); }
+ }
+}
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19552.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19552.stderr
new file mode 100644
index 000000000..f77d94a24
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19552.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `line` does not live long enough
+ --> $DIR/regions-pattern-typing-issue-19552.rs:5:14
+ |
+LL | match [&*line] {
+ | ^^^^ borrowed value does not live long enough
+LL | [ word ] => { assert_static(word); }
+ | ------------------- argument requires that `line` is borrowed for `'static`
+LL | }
+LL | }
+ | - `line` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.rs b/src/test/ui/regions/regions-pattern-typing-issue-19997.rs
new file mode 100644
index 000000000..39190697f
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.rs
@@ -0,0 +1,11 @@
+fn main() {
+ let a0 = 0;
+ let f = 1;
+ let mut a1 = &a0;
+ match (&a1,) {
+ (&ref b0,) => {
+ a1 = &f; //~ ERROR cannot assign to `a1` because it is borrowed
+ drop(b0);
+ }
+ }
+}
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.stderr
new file mode 100644
index 000000000..ae60e3c0d
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `a1` because it is borrowed
+ --> $DIR/regions-pattern-typing-issue-19997.rs:7:13
+ |
+LL | match (&a1,) {
+ | --- borrow of `a1` occurs here
+LL | (&ref b0,) => {
+LL | a1 = &f;
+ | ^^^^^^^ assignment to borrowed `a1` occurs here
+LL | drop(b0);
+ | -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs
new file mode 100644
index 000000000..f79d9dc90
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.rs
@@ -0,0 +1,13 @@
+fn borrowed_proc<'a>(x: &'a isize) -> Box<dyn FnMut()->(isize) + 'a> {
+ // This is legal, because the region bound on `proc`
+ // states that it captures `x`.
+ Box::new(move|| { *x })
+}
+
+fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+ // This is illegal, because the region bound on `proc` is 'static.
+ Box::new(move || { *x })
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
new file mode 100644
index 000000000..60c5246e2
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -0,0 +1,20 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-proc-bound-capture.rs:9:5
+ |
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+ | - let's call the lifetime of this reference `'1`
+LL | // This is illegal, because the region bound on `proc` is 'static.
+LL | Box::new(move || { *x })
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+ |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
+ |
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + '_> {
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn static_proc(x: &'static isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+ | ~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-reassign-let-bound-pointer.rs b/src/test/ui/regions/regions-reassign-let-bound-pointer.rs
new file mode 100644
index 000000000..948b11e0f
--- /dev/null
+++ b/src/test/ui/regions/regions-reassign-let-bound-pointer.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+// Check that the type checker permits us to reassign `z` which
+// started out with a longer lifetime and was reassigned to a shorter
+// one (it should infer to be the intersection).
+
+// pretty-expanded FIXME #23616
+
+fn foo(x: &isize) {
+ let a = 1;
+ let mut z = x;
+ z = &a;
+}
+
+pub fn main() {
+ foo(&1);
+}
diff --git a/src/test/ui/regions/regions-reassign-match-bound-pointer.rs b/src/test/ui/regions/regions-reassign-match-bound-pointer.rs
new file mode 100644
index 000000000..ca52659c4
--- /dev/null
+++ b/src/test/ui/regions/regions-reassign-match-bound-pointer.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+// Check that the type checker permits us to reassign `z` which
+// started out with a longer lifetime and was reassigned to a shorter
+// one (it should infer to be the intersection).
+
+// pretty-expanded FIXME #23616
+
+fn foo(x: &isize) {
+ let a = 1;
+ match x {
+ mut z => {
+ z = &a;
+ }
+ }
+}
+
+pub fn main() {
+ foo(&1);
+}
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs
new file mode 100644
index 000000000..57871b098
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs
@@ -0,0 +1,9 @@
+// Issue #8624. Test for reborrowing with 3 levels, not just two.
+
+fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
+ &mut ***p
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr
new file mode 100644
index 000000000..dc905d076
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:4:5
+ |
+LL | fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | &mut ***p
+ | ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs
new file mode 100644
index 000000000..88cc54650
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs
@@ -0,0 +1,16 @@
+// Issue #8624. Tests that reborrowing the contents of an `&'b mut`
+// pointer which is backed by another `&'a mut` can only be done
+// for `'a` (which must be a sublifetime of `'b`).
+
+fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
+ &mut **p
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+ let mut x = 1;
+ let mut y = &mut x;
+ let z = copy_borrowed_ptr(&mut y);
+ *y += 1;
+ *z += 1;
+}
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr
new file mode 100644
index 000000000..c98ec4774
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:6:5
+ |
+LL | fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | &mut **p
+ | ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-ref-in-fn-arg.rs b/src/test/ui/regions/regions-ref-in-fn-arg.rs
new file mode 100644
index 000000000..3df529c9f
--- /dev/null
+++ b/src/test/ui/regions/regions-ref-in-fn-arg.rs
@@ -0,0 +1,14 @@
+#![feature(box_patterns)]
+
+
+fn arg_item(box ref x: Box<isize>) -> &'static isize {
+ x //~ ERROR cannot return value referencing function parameter
+}
+
+fn with<R, F>(f: F) -> R where F: FnOnce(Box<isize>) -> R { f(Box::new(3)) }
+
+fn arg_closure() -> &'static isize {
+ with(|box ref x| x) //~ ERROR cannot return value referencing function parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-ref-in-fn-arg.stderr b/src/test/ui/regions/regions-ref-in-fn-arg.stderr
new file mode 100644
index 000000000..ccba6c59b
--- /dev/null
+++ b/src/test/ui/regions/regions-ref-in-fn-arg.stderr
@@ -0,0 +1,19 @@
+error[E0515]: cannot return value referencing function parameter
+ --> $DIR/regions-ref-in-fn-arg.rs:5:5
+ |
+LL | fn arg_item(box ref x: Box<isize>) -> &'static isize {
+ | --------- function parameter borrowed here
+LL | x
+ | ^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing function parameter
+ --> $DIR/regions-ref-in-fn-arg.rs:11:22
+ |
+LL | with(|box ref x| x)
+ | --------- ^ returns a value referencing data owned by the current function
+ | |
+ | function parameter borrowed here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-refcell.rs b/src/test/ui/regions/regions-refcell.rs
new file mode 100644
index 000000000..39ad0c53f
--- /dev/null
+++ b/src/test/ui/regions/regions-refcell.rs
@@ -0,0 +1,45 @@
+// run-pass
+// This is a regression test for something that only came up while
+// attempting to bootstrap librustc with new destructor lifetime
+// semantics.
+
+
+use std::collections::HashMap;
+use std::cell::RefCell;
+
+// This version does not yet work (associated type issues)...
+#[cfg(cannot_use_this_yet)]
+fn foo<'a>(map: RefCell<HashMap<&'static str, &'a [u8]>>) {
+ let one = [1];
+ assert_eq!(map.borrow().get("one"), Some(&one[..]));
+}
+
+#[cfg(cannot_use_this_yet_either)]
+// ... and this version does not work (the lifetime of `one` is
+// supposed to match the lifetime `'a`) ...
+fn foo<'a>(map: RefCell<HashMap<&'static str, &'a [u8]>>) {
+ let one = [1];
+ assert_eq!(map.borrow().get("one"), Some(&&one[..]));
+}
+
+#[cfg(all(not(cannot_use_this_yet),not(cannot_use_this_yet_either)))]
+fn foo<'a>(map: RefCell<HashMap<&'static str, &'a [u8]>>) {
+ // ...so instead we walk through the trivial slice and make sure
+ // it contains the element we expect.
+
+ for (i, &x) in map.borrow().get("one").unwrap().iter().enumerate() {
+ assert_eq!((i, x), (0, 1));
+ }
+}
+
+fn main() {
+ let zer = [0];
+ let one = [1];
+ let two = [2];
+ let mut map = HashMap::new();
+ map.insert("zero", &zer[..]);
+ map.insert("one", &one[..]);
+ map.insert("two", &two[..]);
+ let map = RefCell::new(map);
+ foo(map);
+}
diff --git a/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs
new file mode 100644
index 000000000..b1bdb813a
--- /dev/null
+++ b/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs
@@ -0,0 +1,57 @@
+// run-pass
+#![allow(dead_code)]
+// Test that this fairly specialized, but also reasonable, pattern
+// typechecks. The pattern involves regions bound in closures that
+// wind up related to inference variables.
+//
+// NB. Changes to the region implementations have broken this pattern
+// a few times, but it happens to be used in the compiler so those
+// changes were caught. However, those uses in the compiler could
+// easily get changed or refactored away in the future.
+
+struct Ctxt<'tcx> {
+ x: &'tcx Vec<isize>
+}
+
+struct Foo<'a,'tcx:'a> {
+ cx: &'a Ctxt<'tcx>,
+}
+
+impl<'a,'tcx> Foo<'a,'tcx> {
+ fn bother(&mut self) -> isize {
+ self.elaborate_bounds(Box::new(|this| {
+ // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`,
+ // where `'f0` and `'f1` are fresh, free regions that
+ // result from the bound regions on the closure, and `'2`
+ // is a region inference variable created by the call. Due
+ // to the constraints on the type, we find that `'_2 : 'f1
+ // + 'f2` must hold (and can be assumed by the callee).
+ // Region inference has to do some clever stuff to avoid
+ // inferring `'_2` to be `'static` in this case, because
+ // it is created outside the closure but then related to
+ // regions bound by the closure itself. See the
+ // `region_constraints.rs` file (and the `givens` field, in
+ // particular) for more details.
+ this.foo()
+ }))
+ }
+
+ fn foo(&mut self) -> isize {
+ 22
+ }
+
+ fn elaborate_bounds(
+ &mut self,
+ mut mk_cand: Box<dyn for<'b> FnMut(&mut Foo<'b, 'tcx>) -> isize>)
+ -> isize
+ {
+ mk_cand(self)
+ }
+}
+
+fn main() {
+ let v = vec![];
+ let cx = Ctxt { x: &v };
+ let mut foo = Foo { cx: &cx };
+ assert_eq!(foo.bother(), 22); // just so the code is not dead, basically
+}
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.rs b/src/test/ui/regions/regions-ret-borrowed-1.rs
new file mode 100644
index 000000000..54630caff
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed-1.rs
@@ -0,0 +1,17 @@
+// Similar to regions-ret-borrowed.rs, but using a named lifetime. At
+// some point regions-ret-borrowed reported an error but this file did
+// not, due to special hardcoding around the anonymous region.
+
+fn with<R, F>(f: F) -> R where F: for<'a> FnOnce(&'a isize) -> R {
+ f(&3)
+}
+
+fn return_it<'a>() -> &'a isize {
+ with(|o| o)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+ let x = return_it();
+ println!("foo={}", *x);
+}
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr
new file mode 100644
index 000000000..0784e894e
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-ret-borrowed-1.rs:10:14
+ |
+LL | with(|o| o)
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 isize
+ | has type `&'1 isize`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-ret-borrowed.rs b/src/test/ui/regions/regions-ret-borrowed.rs
new file mode 100644
index 000000000..bdb0341c9
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed.rs
@@ -0,0 +1,20 @@
+// Ensure that you cannot use generic types to return a region outside
+// of its bound. Here, in the `return_it()` fn, we call with() but
+// with R bound to &isize from the return_it. Meanwhile, with()
+// provides a value that is only good within its own stack frame. This
+// used to successfully compile because we failed to account for the
+// fact that fn(x: &isize) rebound the region &.
+
+fn with<R, F>(f: F) -> R where F: FnOnce(&isize) -> R {
+ f(&3)
+}
+
+fn return_it<'a>() -> &'a isize {
+ with(|o| o)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+ let x = return_it();
+ println!("foo={}", *x);
+}
diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr
new file mode 100644
index 000000000..d9be5ef89
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-ret-borrowed.rs:13:14
+ |
+LL | with(|o| o)
+ | -- ^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure is &'2 isize
+ | has type `&'1 isize`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-ret.rs b/src/test/ui/regions/regions-ret.rs
new file mode 100644
index 000000000..580545ef8
--- /dev/null
+++ b/src/test/ui/regions/regions-ret.rs
@@ -0,0 +1,8 @@
+fn id<T>(x: T) -> T { x }
+
+fn f(_x: &isize) -> &isize {
+ return &id(3); //~ ERROR cannot return reference to temporary value
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-ret.stderr b/src/test/ui/regions/regions-ret.stderr
new file mode 100644
index 000000000..0e4875ac9
--- /dev/null
+++ b/src/test/ui/regions/regions-ret.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/regions-ret.rs:4:12
+ |
+LL | return &id(3);
+ | ^-----
+ | ||
+ | |temporary value created here
+ | returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-return-interior-of-option.rs b/src/test/ui/regions/regions-return-interior-of-option.rs
new file mode 100644
index 000000000..2dc91ec84
--- /dev/null
+++ b/src/test/ui/regions/regions-return-interior-of-option.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+fn get<T>(opt: &Option<T>) -> &T {
+ match *opt {
+ Some(ref v) => v,
+ None => panic!("none")
+ }
+}
+
+pub fn main() {
+ let mut x = Some(23);
+
+ {
+ let y = get(&x);
+ assert_eq!(*y, 23);
+ }
+
+ x = Some(24);
+
+ {
+ let y = get(&x);
+ assert_eq!(*y, 24);
+ }
+}
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
new file mode 100644
index 000000000..86e759f08
--- /dev/null
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
@@ -0,0 +1,11 @@
+// Test that closures cannot subvert aliasing restrictions
+
+fn main() {
+ // Unboxed closure case
+ {
+ let mut x = 0;
+ let mut f = || &mut x; //~ ERROR captured variable cannot escape `FnMut` closure body
+ let x = f();
+ let y = f();
+ }
+}
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
new file mode 100644
index 000000000..b087e03b4
--- /dev/null
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
@@ -0,0 +1,17 @@
+error: captured variable cannot escape `FnMut` closure body
+ --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
+ |
+LL | let mut x = 0;
+ | ----- variable defined here
+LL | let mut f = || &mut x;
+ | - ^^^^^-
+ | | | |
+ | | | variable captured here
+ | | returns a reference to a captured variable which escapes the closure body
+ | inferred to be a `FnMut` closure
+ |
+ = note: `FnMut` closures only have access to their captured variables while they are executing...
+ = note: ...therefore, they cannot allow references to captured variables to escape
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-return-stack-allocated-vec.rs b/src/test/ui/regions/regions-return-stack-allocated-vec.rs
new file mode 100644
index 000000000..97fbdbf46
--- /dev/null
+++ b/src/test/ui/regions/regions-return-stack-allocated-vec.rs
@@ -0,0 +1,10 @@
+// Test that we cannot return a stack allocated slice
+
+fn function(x: isize) -> &'static [isize] {
+ &[x] //~ ERROR cannot return reference to temporary value
+}
+
+fn main() {
+ let x = function(1);
+ let y = x[0];
+}
diff --git a/src/test/ui/regions/regions-return-stack-allocated-vec.stderr b/src/test/ui/regions/regions-return-stack-allocated-vec.stderr
new file mode 100644
index 000000000..9d87fe266
--- /dev/null
+++ b/src/test/ui/regions/regions-return-stack-allocated-vec.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/regions-return-stack-allocated-vec.rs:4:5
+ |
+LL | &[x]
+ | ^---
+ | ||
+ | |temporary value created here
+ | returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-scope-chain-example.rs b/src/test/ui/regions/regions-scope-chain-example.rs
new file mode 100644
index 000000000..2beb20add
--- /dev/null
+++ b/src/test/ui/regions/regions-scope-chain-example.rs
@@ -0,0 +1,43 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// This is an example where the older inference algorithm failed. The
+// specifics of why it failed are somewhat, but not entirely, tailed
+// to the algorithm. Ultimately the problem is that when computing the
+// mutual supertype of both sides of the `if` it would be faced with a
+// choice of tightening bounds or unifying variables and it took the
+// wrong path. The new algorithm avoids this problem and hence this
+// example typechecks correctly.
+
+// pretty-expanded FIXME #23616
+
+enum ScopeChain<'a> {
+ Link(Scope<'a>),
+ End
+}
+
+type Scope<'a> = &'a ScopeChain<'a>;
+
+struct OuterContext;
+
+struct Context<'a> {
+ foo: &'a OuterContext
+}
+
+impl<'a> Context<'a> {
+ fn foo(&mut self, scope: Scope) {
+ let link = if 1 < 2 {
+ let l = ScopeChain::Link(scope);
+ self.take_scope(&l);
+ l
+ } else {
+ ScopeChain::Link(scope)
+ };
+ self.take_scope(&link);
+ }
+
+ fn take_scope(&mut self, x: Scope) {
+ }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-self-impls.rs b/src/test/ui/regions/regions-self-impls.rs
new file mode 100644
index 000000000..80b88568e
--- /dev/null
+++ b/src/test/ui/regions/regions-self-impls.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+struct Clam<'a> {
+ chowder: &'a isize
+}
+
+trait get_chowder<'a> {
+ fn get_chowder(&self) -> &'a isize;
+}
+
+impl<'a> get_chowder<'a> for Clam<'a> {
+ fn get_chowder(&self) -> &'a isize { return self.chowder; }
+}
+
+pub fn main() {
+ let clam = Clam { chowder: &3 };
+ println!("{}", *clam.get_chowder());
+ clam.get_chowder();
+}
diff --git a/src/test/ui/regions/regions-self-in-enums.rs b/src/test/ui/regions/regions-self-in-enums.rs
new file mode 100644
index 000000000..c2e4b2ff1
--- /dev/null
+++ b/src/test/ui/regions/regions-self-in-enums.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(unused_mut)]
+#![allow(non_camel_case_types)]
+
+enum int_wrapper<'a> {
+ int_wrapper_ctor(&'a isize)
+}
+
+pub fn main() {
+ let x = 3;
+ let y = int_wrapper::int_wrapper_ctor(&x);
+ let mut z : &isize;
+ match y {
+ int_wrapper::int_wrapper_ctor(zz) => { z = zz; }
+ }
+ println!("{}", *z);
+}
diff --git a/src/test/ui/regions/regions-simple.rs b/src/test/ui/regions/regions-simple.rs
new file mode 100644
index 000000000..fff1b47f5
--- /dev/null
+++ b/src/test/ui/regions/regions-simple.rs
@@ -0,0 +1,7 @@
+// run-pass
+pub fn main() {
+ let mut x: isize = 3;
+ let y: &mut isize = &mut x;
+ *y = 5;
+ println!("{}", *y);
+}
diff --git a/src/test/ui/regions/regions-static-bound-rpass.rs b/src/test/ui/regions/regions-static-bound-rpass.rs
new file mode 100644
index 000000000..25232b455
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound-rpass.rs
@@ -0,0 +1,26 @@
+// run-pass
+
+fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
+ where 'a: 'static { t }
+//~^ WARN unnecessary lifetime parameter `'a`
+
+fn static_id<'a>(t: &'a ()) -> &'static ()
+ where 'a: 'static { t }
+//~^ WARN unnecessary lifetime parameter `'a`
+
+fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
+ where 'a: 'b, 'b: 'static { t }
+//~^ WARN unnecessary lifetime parameter `'b`
+
+fn ref_id<'a>(t: &'a ()) -> &'a () where 'static: 'a { t }
+
+static UNIT: () = ();
+
+fn main()
+{
+ let mut val : &'static () = &UNIT;
+ invariant_id(&mut val);
+ static_id(val);
+ static_id_indirect(val);
+ ref_id(val);
+}
diff --git a/src/test/ui/regions/regions-static-bound-rpass.stderr b/src/test/ui/regions/regions-static-bound-rpass.stderr
new file mode 100644
index 000000000..9355a409d
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound-rpass.stderr
@@ -0,0 +1,26 @@
+warning: unnecessary lifetime parameter `'a`
+ --> $DIR/regions-static-bound-rpass.rs:4:11
+ |
+LL | where 'a: 'static { t }
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'a`
+
+warning: unnecessary lifetime parameter `'a`
+ --> $DIR/regions-static-bound-rpass.rs:8:11
+ |
+LL | where 'a: 'static { t }
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'a`
+
+warning: unnecessary lifetime parameter `'b`
+ --> $DIR/regions-static-bound-rpass.rs:12:19
+ |
+LL | where 'a: 'b, 'b: 'static { t }
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'b`
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/regions/regions-static-bound.rs b/src/test/ui/regions/regions-static-bound.rs
new file mode 100644
index 000000000..4d2455470
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound.rs
@@ -0,0 +1,21 @@
+fn static_id<'a,'b>(t: &'a ()) -> &'static ()
+ where 'a: 'static { t }
+//~^ WARN unnecessary lifetime parameter `'a`
+
+fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
+ where 'a: 'b, 'b: 'static { t }
+//~^ WARN unnecessary lifetime parameter `'b`
+
+fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
+ t
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn error(u: &(), v: &()) {
+ static_id(&u);
+ //~^ ERROR borrowed data escapes outside of function [E0521]
+ static_id_indirect(&v);
+ //~^ ERROR borrowed data escapes outside of function [E0521]
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-static-bound.stderr b/src/test/ui/regions/regions-static-bound.stderr
new file mode 100644
index 000000000..2886ec3ea
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound.stderr
@@ -0,0 +1,54 @@
+warning: unnecessary lifetime parameter `'a`
+ --> $DIR/regions-static-bound.rs:2:11
+ |
+LL | where 'a: 'static { t }
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'a`
+
+warning: unnecessary lifetime parameter `'b`
+ --> $DIR/regions-static-bound.rs:6:19
+ |
+LL | where 'a: 'b, 'b: 'static { t }
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-static-bound.rs:10:5
+ |
+LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
+ | -- lifetime `'a` defined here
+LL | t
+ | ^ returning this value requires that `'a` must outlive `'static`
+
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/regions-static-bound.rs:15:5
+ |
+LL | fn error(u: &(), v: &()) {
+ | - - let's call the lifetime of this reference `'1`
+ | |
+ | `u` is a reference that is only valid in the function body
+LL | static_id(&u);
+ | ^^^^^^^^^^^^^
+ | |
+ | `u` escapes the function body here
+ | argument requires that `'1` must outlive `'static`
+
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/regions-static-bound.rs:17:5
+ |
+LL | fn error(u: &(), v: &()) {
+ | - - let's call the lifetime of this reference `'2`
+ | |
+ | `v` is a reference that is only valid in the function body
+...
+LL | static_id_indirect(&v);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `v` escapes the function body here
+ | argument requires that `'2` must outlive `'static`
+
+error: aborting due to 3 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/regions/regions-static-closure.rs b/src/test/ui/regions/regions-static-closure.rs
new file mode 100644
index 000000000..09cd56220
--- /dev/null
+++ b/src/test/ui/regions/regions-static-closure.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+struct closure_box<'a> {
+ cl: Box<dyn FnMut() + 'a>,
+}
+
+fn box_it<'a>(x: Box<dyn FnMut() + 'a>) -> closure_box<'a> {
+ closure_box {cl: x}
+}
+
+fn call_static_closure(mut cl: closure_box<'static>) {
+ (cl.cl)();
+}
+
+pub fn main() {
+ let cl_box = box_it(Box::new(|| println!("Hello, world!")));
+ call_static_closure(cl_box);
+}
diff --git a/src/test/ui/regions/regions-steal-closure.rs b/src/test/ui/regions/regions-steal-closure.rs
new file mode 100644
index 000000000..83e93522c
--- /dev/null
+++ b/src/test/ui/regions/regions-steal-closure.rs
@@ -0,0 +1,17 @@
+#![feature(fn_traits)]
+
+struct ClosureBox<'a> {
+ cl: Box<dyn FnMut() + 'a>,
+}
+
+fn box_it<'r>(x: Box<dyn FnMut() + 'r>) -> ClosureBox<'r> {
+ ClosureBox {cl: x}
+}
+
+fn main() {
+ let mut cl_box = {
+ let mut i = 3;
+ box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough
+ };
+ cl_box.cl.call_mut(());
+}
diff --git a/src/test/ui/regions/regions-steal-closure.stderr b/src/test/ui/regions/regions-steal-closure.stderr
new file mode 100644
index 000000000..5b0efaf95
--- /dev/null
+++ b/src/test/ui/regions/regions-steal-closure.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `i` does not live long enough
+ --> $DIR/regions-steal-closure.rs:14:28
+ |
+LL | let mut cl_box = {
+ | ---------- borrow later stored here
+LL | let mut i = 3;
+LL | box_it(Box::new(|| i += 1))
+ | -- ^ borrowed value does not live long enough
+ | |
+ | value captured here
+LL | };
+ | - `i` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-trait-1.rs b/src/test/ui/regions/regions-trait-1.rs
new file mode 100644
index 000000000..b6dab1c32
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-1.rs
@@ -0,0 +1,33 @@
+// check-pass
+
+struct Ctxt {
+ v: usize,
+}
+
+trait GetCtxt {
+ // Here the `&` is bound in the method definition:
+ fn get_ctxt(&self) -> &Ctxt;
+}
+
+struct HasCtxt<'a> {
+ c: &'a Ctxt,
+}
+
+impl<'a> GetCtxt for HasCtxt<'a> {
+ // Ok: Have implied bound of WF(&'b HasCtxt<'a>)
+ // so know 'a: 'b
+ // so know &'a Ctxt <: &'b Ctxt
+ fn get_ctxt<'b>(&'b self) -> &'a Ctxt {
+ self.c
+ }
+}
+
+fn get_v(gc: Box<dyn GetCtxt + '_>) -> usize {
+ gc.get_ctxt().v
+}
+
+fn main() {
+ let ctxt = Ctxt { v: 22 };
+ let hc = HasCtxt { c: &ctxt };
+ assert_eq!(get_v(Box::new(hc) as Box<dyn GetCtxt>), 22);
+}
diff --git a/src/test/ui/regions/regions-trait-object-1.rs b/src/test/ui/regions/regions-trait-object-1.rs
new file mode 100644
index 000000000..e2520d978
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-object-1.rs
@@ -0,0 +1,35 @@
+// run-pass
+// This is a regression test for something that only came up while
+// attempting to bootstrap librustc_ast; it is adapted from
+// `rustc_ast::ext::tt::generic_extension`.
+
+
+pub struct E<'a> {
+ pub f: &'a u8,
+}
+impl<'b> E<'b> {
+ pub fn m(&self) -> &'b u8 { self.f }
+}
+
+pub struct P<'c> {
+ pub g: &'c u8,
+}
+pub trait M {
+ fn n(&self) -> u8;
+}
+impl<'d> M for P<'d> {
+ fn n(&self) -> u8 { *self.g }
+}
+
+fn extension<'e>(x: &'e E<'e>) -> Box<dyn M+'e> {
+ loop {
+ let p = P { g: x.m() };
+ return Box::new(p) as Box<dyn M+'e>;
+ }
+}
+
+fn main() {
+ let w = E { f: &10 };
+ let o = extension(&w);
+ assert_eq!(o.n(), 10);
+}
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.rs b/src/test/ui/regions/regions-trait-object-subtyping.rs
new file mode 100644
index 000000000..1d7a766de
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-object-subtyping.rs
@@ -0,0 +1,26 @@
+trait Dummy { fn dummy(&self); }
+
+fn foo1<'a:'b,'b>(x: &'a mut (dyn Dummy+'a)) -> &'b mut (dyn Dummy+'b) {
+ // Here, we are able to coerce
+ x
+}
+
+fn foo2<'a:'b,'b>(x: &'b mut (dyn Dummy+'a)) -> &'b mut (dyn Dummy+'b) {
+ // Here, we are able to coerce
+ x
+}
+
+fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
+ // Without knowing 'a:'b, we can't coerce
+ x
+ //~^ ERROR lifetime may not live long enough
+}
+
+struct Wrapper<T>(T);
+fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> {
+ // We can't coerce because it is packed in `Wrapper`
+ x
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr
new file mode 100644
index 000000000..1b3a116d5
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr
@@ -0,0 +1,34 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-trait-object-subtyping.rs:15:5
+ |
+LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // Without knowing 'a:'b, we can't coerce
+LL | x
+ | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+ = note: requirement occurs because of a mutable reference to `dyn Dummy`
+ = note: mutable references are invariant over their type parameter
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+ --> $DIR/regions-trait-object-subtyping.rs:22:5
+ |
+LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // We can't coerce because it is packed in `Wrapper`
+LL | x
+ | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+ = note: requirement occurs because of a mutable reference to `dyn Dummy`
+ = note: mutable references are invariant over their type parameter
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/regions/regions-trait-variance.rs b/src/test/ui/regions/regions-trait-variance.rs
new file mode 100644
index 000000000..94ffb85c9
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-variance.rs
@@ -0,0 +1,44 @@
+// Issue #12470.
+
+trait X {
+ fn get_i(&self) -> isize;
+}
+
+struct B {
+ i: isize
+}
+
+impl X for B {
+ fn get_i(&self) -> isize {
+ self.i
+ }
+}
+
+impl Drop for B {
+ fn drop(&mut self) {
+ println!("drop");
+ }
+}
+
+struct A<'r> {
+ p: &'r (dyn X + 'r)
+}
+
+fn make_a(p: &dyn X) -> A {
+ A{p:p}
+}
+
+fn make_make_a<'a>() -> A<'a> {
+
+ let b: Box<B> = Box::new(B {
+ i: 1,
+ });
+
+ let bb: &B = &*b;
+ make_a(bb) //~ ERROR cannot return value referencing local data `*b`
+}
+
+fn main() {
+ let a = make_make_a();
+ println!("{}", a.p.get_i());
+}
diff --git a/src/test/ui/regions/regions-trait-variance.stderr b/src/test/ui/regions/regions-trait-variance.stderr
new file mode 100644
index 000000000..56c9f89e1
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-variance.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing local data `*b`
+ --> $DIR/regions-trait-variance.rs:38:5
+ |
+LL | let bb: &B = &*b;
+ | --- `*b` is borrowed here
+LL | make_a(bb)
+ | ^^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-undeclared.rs b/src/test/ui/regions/regions-undeclared.rs
new file mode 100644
index 000000000..1edd998aa
--- /dev/null
+++ b/src/test/ui/regions/regions-undeclared.rs
@@ -0,0 +1,13 @@
+static c_x: &'blk isize = &22; //~ ERROR use of undeclared lifetime name `'blk`
+
+enum EnumDecl {
+ Foo(&'a isize), //~ ERROR use of undeclared lifetime name `'a`
+ Bar(&'a isize), //~ ERROR use of undeclared lifetime name `'a`
+}
+
+fn fnDecl(x: &'a isize, //~ ERROR use of undeclared lifetime name `'a`
+ y: &'a isize) //~ ERROR use of undeclared lifetime name `'a`
+{}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-undeclared.stderr b/src/test/ui/regions/regions-undeclared.stderr
new file mode 100644
index 000000000..6bfde5524
--- /dev/null
+++ b/src/test/ui/regions/regions-undeclared.stderr
@@ -0,0 +1,42 @@
+error[E0261]: use of undeclared lifetime name `'blk`
+ --> $DIR/regions-undeclared.rs:1:14
+ |
+LL | static c_x: &'blk isize = &22;
+ | ^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-undeclared.rs:4:10
+ |
+LL | enum EnumDecl {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | Foo(&'a isize),
+ | ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-undeclared.rs:5:10
+ |
+LL | enum EnumDecl {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | Foo(&'a isize),
+LL | Bar(&'a isize),
+ | ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-undeclared.rs:8:15
+ |
+LL | fn fnDecl(x: &'a isize,
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/regions-undeclared.rs:9:15
+ |
+LL | fn fnDecl(x: &'a isize,
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | y: &'a isize)
+ | ^^ undeclared lifetime
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.rs b/src/test/ui/regions/regions-var-type-out-of-scope.rs
new file mode 100644
index 000000000..aba55e9df
--- /dev/null
+++ b/src/test/ui/regions/regions-var-type-out-of-scope.rs
@@ -0,0 +1,14 @@
+fn id<T>(x: T) -> T { x }
+
+fn foo(cond: bool) {
+ // Here we will infer a type that uses the
+ // region of the if stmt then block:
+ let mut x;
+
+ if cond {
+ x = &id(3); //~ ERROR temporary value dropped while borrowed
+ assert_eq!(*x, 3);
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.stderr
new file mode 100644
index 000000000..476e82f04
--- /dev/null
+++ b/src/test/ui/regions/regions-var-type-out-of-scope.stderr
@@ -0,0 +1,15 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/regions-var-type-out-of-scope.rs:9:14
+ |
+LL | x = &id(3);
+ | ^^^^^- temporary value is freed at the end of this statement
+ | |
+ | creates a temporary which is freed while still in use
+LL | assert_eq!(*x, 3);
+ | ----------------- borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs b/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs
new file mode 100644
index 000000000..e63778670
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs
@@ -0,0 +1,27 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test that a type which is contravariant with respect to its region
+// parameter compiles successfully when used in a contravariant way.
+//
+// Note: see ui/variance/variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// pretty-expanded FIXME #23616
+
+struct Contravariant<'a> {
+ f: &'a isize
+}
+
+fn use_<'a>(c: Contravariant<'a>) {
+ let x = 3;
+
+ // 'b winds up being inferred to this call.
+ // Contravariant<'a> <: Contravariant<'call> is true
+ // if 'call <= 'a, which is true, so no error.
+ collapse(&x, c);
+
+ fn collapse<'b>(x: &'b isize, c: Contravariant<'b>) { }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs
new file mode 100644
index 000000000..f23ca537f
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs
@@ -0,0 +1,29 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// `S` is contravariant with respect to both parameters.
+struct S<'a, 'b> {
+ f: &'a isize,
+ g: &'b isize,
+}
+
+fn use_<'short,'long>(c: S<'long, 'short>,
+ s: &'short isize,
+ l: &'long isize,
+ _where:Option<&'short &'long ()>) {
+
+ let _: S<'long, 'short> = c; // OK
+ let _: S<'short, 'short> = c; // OK
+
+ // Test whether S<_,'short> <: S<_,'long>. Since
+ // 'short <= 'long, this would be true if the Contravariant type were
+ // covariant with respect to its parameter 'a.
+
+ let _: S<'long, 'long> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr
new file mode 100644
index 000000000..5352be430
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-variance-contravariant-use-covariant-in-second-position.rs:25:12
+ |
+LL | fn use_<'short,'long>(c: S<'long, 'short>,
+ | ------ ----- lifetime `'long` defined here
+ | |
+ | lifetime `'short` defined here
+...
+LL | let _: S<'long, 'long> = c;
+ | ^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+ |
+ = help: consider adding the following bound: `'short: 'long`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant.rs b/src/test/ui/regions/regions-variance-contravariant-use-covariant.rs
new file mode 100644
index 000000000..c73577cb3
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant.rs
@@ -0,0 +1,27 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// This is contravariant with respect to 'a, meaning that
+// Contravariant<'long> <: Contravariant<'short> iff
+// 'short <= 'long
+struct Contravariant<'a> {
+ f: &'a isize
+}
+
+fn use_<'short,'long>(c: Contravariant<'short>,
+ s: &'short isize,
+ l: &'long isize,
+ _where:Option<&'short &'long ()>) {
+
+ // Test whether Contravariant<'short> <: Contravariant<'long>. Since
+ // 'short <= 'long, this would be true if the Contravariant type were
+ // covariant with respect to its parameter 'a.
+
+ let _: Contravariant<'long> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr
new file mode 100644
index 000000000..22c9b915b
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-variance-contravariant-use-covariant.rs:23:12
+ |
+LL | fn use_<'short,'long>(c: Contravariant<'short>,
+ | ------ ----- lifetime `'long` defined here
+ | |
+ | lifetime `'short` defined here
+...
+LL | let _: Contravariant<'long> = c;
+ | ^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+ |
+ = help: consider adding the following bound: `'short: 'long`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-variance-covariant-use-contravariant.rs b/src/test/ui/regions/regions-variance-covariant-use-contravariant.rs
new file mode 100644
index 000000000..a2183b491
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-covariant-use-contravariant.rs
@@ -0,0 +1,27 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// This is covariant with respect to 'a, meaning that
+// Covariant<'foo> <: Covariant<'static> because
+// 'foo <= 'static
+struct Covariant<'a> {
+ f: extern "Rust" fn(&'a isize)
+}
+
+fn use_<'short,'long>(c: Covariant<'long>,
+ s: &'short isize,
+ l: &'long isize,
+ _where:Option<&'short &'long ()>) {
+
+ // Test whether Covariant<'long> <: Covariant<'short>. Since
+ // 'short <= 'long, this would be true if the Covariant type were
+ // contravariant with respect to its parameter 'a.
+
+ let _: Covariant<'short> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr b/src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr
new file mode 100644
index 000000000..a07181ad5
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-variance-covariant-use-contravariant.rs:23:12
+ |
+LL | fn use_<'short,'long>(c: Covariant<'long>,
+ | ------ ----- lifetime `'long` defined here
+ | |
+ | lifetime `'short` defined here
+...
+LL | let _: Covariant<'short> = c;
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+ |
+ = help: consider adding the following bound: `'short: 'long`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-variance-covariant-use-covariant.rs b/src/test/ui/regions/regions-variance-covariant-use-covariant.rs
new file mode 100644
index 000000000..c5c80ce54
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-covariant-use-covariant.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+// Test that a type which is covariant with respect to its region
+// parameter is successful when used in a covariant way.
+//
+// Note: see ui/variance/variance-regions-*.rs for the tests that
+// check that the variance inference works in the first place.
+
+// This is covariant with respect to 'a, meaning that
+// Covariant<'foo> <: Covariant<'static> because
+// 'foo <= 'static
+// pretty-expanded FIXME #23616
+
+struct Covariant<'a> {
+ f: extern "Rust" fn(&'a isize)
+}
+
+fn use_<'a>(c: Covariant<'a>) {
+ // OK Because Covariant<'a> <: Covariant<'static> iff 'a <= 'static
+ let _: Covariant<'static> = c;
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-variance-invariant-use-contravariant.rs b/src/test/ui/regions/regions-variance-invariant-use-contravariant.rs
new file mode 100644
index 000000000..a81aaa9c7
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-contravariant.rs
@@ -0,0 +1,24 @@
+// Test that an invariant region parameter used in a contravariant way
+// yields an error.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+struct Invariant<'a> {
+ f: &'a mut &'a isize
+}
+
+fn use_<'short,'long>(c: Invariant<'long>,
+ s: &'short isize,
+ l: &'long isize,
+ _where:Option<&'short &'long ()>) {
+
+ // Test whether Invariant<'long> <: Invariant<'short>. Since
+ // 'short <= 'long, this would be true if the Invariant type were
+ // contravariant with respect to its parameter 'a.
+
+ let _: Invariant<'short> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr
new file mode 100644
index 000000000..b35a2cb90
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-variance-invariant-use-contravariant.rs:20:12
+ |
+LL | fn use_<'short,'long>(c: Invariant<'long>,
+ | ------ ----- lifetime `'long` defined here
+ | |
+ | lifetime `'short` defined here
+...
+LL | let _: Invariant<'short> = c;
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+ |
+ = help: consider adding the following bound: `'short: 'long`
+ = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.rs b/src/test/ui/regions/regions-variance-invariant-use-covariant.rs
new file mode 100644
index 000000000..ab6a82ee7
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.rs
@@ -0,0 +1,21 @@
+// Test that a type which is invariant with respect to its region
+// parameter used in a covariant way yields an error.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+struct Invariant<'a> {
+ f: &'a mut &'a isize
+}
+
+fn use_<'b>(c: Invariant<'b>) {
+
+ // For this assignment to be legal, Invariant<'b> <: Invariant<'static>.
+ // Since 'b <= 'static, this would be true if Invariant were covariant
+ // with respect to its parameter 'a.
+
+ let _: Invariant<'static> = c;
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr
new file mode 100644
index 000000000..761e78d17
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-variance-invariant-use-covariant.rs:17:12
+ |
+LL | fn use_<'b>(c: Invariant<'b>) {
+ | -- lifetime `'b` defined here
+...
+LL | let _: Invariant<'static> = c;
+ | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'static`
+ |
+ = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-wf-trait-object.rs b/src/test/ui/regions/regions-wf-trait-object.rs
new file mode 100644
index 000000000..d0053b202
--- /dev/null
+++ b/src/test/ui/regions/regions-wf-trait-object.rs
@@ -0,0 +1,10 @@
+// Check that the explicit lifetime bound (`'b`, in this example) must
+// outlive all the superbound from the trait (`'a`, in this example).
+
+trait TheTrait<'t>: 't { }
+
+struct Foo<'a,'b> {
+ x: Box<dyn TheTrait<'a>+'b> //~ ERROR E0478
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-wf-trait-object.stderr b/src/test/ui/regions/regions-wf-trait-object.stderr
new file mode 100644
index 000000000..f6006ca04
--- /dev/null
+++ b/src/test/ui/regions/regions-wf-trait-object.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/regions-wf-trait-object.rs:7:8
+ |
+LL | x: Box<dyn TheTrait<'a>+'b>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lifetime parameter instantiated with the lifetime `'b` as defined here
+ --> $DIR/regions-wf-trait-object.rs:6:15
+ |
+LL | struct Foo<'a,'b> {
+ | ^^
+note: but lifetime parameter must outlive the lifetime `'a` as defined here
+ --> $DIR/regions-wf-trait-object.rs:6:12
+ |
+LL | struct Foo<'a,'b> {
+ | ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs b/src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
new file mode 100644
index 000000000..a65c17e0e
--- /dev/null
+++ b/src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
@@ -0,0 +1,66 @@
+// Regression test for #74429, where we didn't think that a type parameter
+// outlived `ReEmpty`.
+
+// check-pass
+
+use std::marker::PhantomData;
+use std::ptr::NonNull;
+
+pub unsafe trait RawData {
+ type Elem;
+}
+
+unsafe impl<A> RawData for OwnedRepr<A> {
+ type Elem = A;
+}
+
+unsafe impl<'a, A> RawData for ViewRepr<&'a A> {
+ type Elem = A;
+}
+
+pub struct OwnedRepr<A> {
+ ptr: PhantomData<A>,
+}
+
+// these Copy impls are not necessary for the repro, but allow the code to compile without error
+// on 1.44.1
+#[derive(Copy, Clone)]
+pub struct ViewRepr<A> {
+ life: PhantomData<A>,
+}
+
+#[derive(Copy, Clone)]
+pub struct ArrayBase<S>
+where
+ S: RawData,
+{
+ ptr: NonNull<S::Elem>,
+}
+
+pub type Array<A> = ArrayBase<OwnedRepr<A>>;
+
+pub type ArrayView<'a, A> = ArrayBase<ViewRepr<&'a A>>;
+
+impl<A, S> ArrayBase<S>
+where
+ S: RawData<Elem = A>,
+{
+ pub fn index_axis(&self) -> ArrayView<'_, A> {
+ unimplemented!()
+ }
+
+ pub fn axis_iter<'a>(&'a self) -> std::iter::Empty<&'a A> {
+ unimplemented!()
+ }
+}
+
+pub fn x<T: Copy>(a: Array<T>) {
+ // drop just avoids a must_use warning
+ drop((0..1).filter(|_| true));
+ let y = a.index_axis();
+ a.axis_iter().for_each(|_| {
+ drop(y);
+ });
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs b/src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs
new file mode 100644
index 000000000..d463f311c
--- /dev/null
+++ b/src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs
@@ -0,0 +1,35 @@
+// Regression test for #74429, where we didn't think that a type parameter
+// outlived `ReEmpty`.
+
+// check-pass
+
+use std::marker::PhantomData;
+
+fn apply<T, F: FnOnce(T)>(_: T, _: F) {}
+
+#[derive(Clone, Copy)]
+struct Invariant<T> {
+ t: T,
+ p: PhantomData<fn(T) -> T>,
+}
+
+fn verify_reempty<T>(x: T) {
+ // r is inferred to have type `Invariant<&ReEmpty(U0) T>`
+ let r = Invariant { t: &x, p: PhantomData };
+ // Creates a new universe, all variables from now on are in `U1`, say.
+ let _: fn(&()) = |_| {};
+ // Closure parameter is of type `&ReEmpty(U1) T`, so the closure has an implied
+ // bound of `T: ReEmpty(U1)`
+ apply(&x, |_| {
+ // Requires `typeof(r)` is well-formed, i.e. `T: ReEmpty(U0)`. If we
+ // only have the implied bound from the closure parameter to use this
+ // requires `ReEmpty(U1): ReEmpty(U0)`, which isn't true so we reported
+ // an error.
+ //
+ // This doesn't happen any more because we ensure that `T: ReEmpty(U0)`
+ // is an implicit bound for all type parameters.
+ drop(r);
+ });
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/wf-bound-region-in-object-type.rs b/src/test/ui/regions/wf-bound-region-in-object-type.rs
new file mode 100644
index 000000000..7c4dd3ec8
--- /dev/null
+++ b/src/test/ui/regions/wf-bound-region-in-object-type.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test that the `wf` checker properly handles bound regions in object
+// types. Compiling this code used to trigger an ICE.
+
+// pretty-expanded FIXME #23616
+
+pub struct Context<'tcx> {
+ vec: &'tcx Vec<isize>
+}
+
+pub type Cmd<'a> = &'a isize;
+
+pub type DecodeInlinedItem<'a> =
+ Box<dyn for<'tcx> FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx isize, ()> + 'a>;
+
+fn foo(d: DecodeInlinedItem) {
+}
+
+fn main() { }